package service

import (
	"baron-sso-backend/internal/domain"
	"baron-sso-backend/internal/repository"
	"context"
	"crypto/sha256"
	"encoding/hex"
	"fmt"
	"strings"
	"time"
)

type RPUsageEventEmitter struct {
	repo repository.RPUsageOutboxRepository
}

func NewRPUsageEventEmitter(repo repository.RPUsageOutboxRepository) *RPUsageEventEmitter {
	return &RPUsageEventEmitter{repo: repo}
}

func (e *RPUsageEventEmitter) EmitRPUsageEvent(ctx context.Context, event domain.RPUsageEvent) error {
	if e == nil || e.repo == nil {
		return nil
	}
	event.EventType = strings.TrimSpace(event.EventType)
	event.Subject = strings.TrimSpace(event.Subject)
	event.ClientID = strings.TrimSpace(event.ClientID)
	event.Source = strings.TrimSpace(event.Source)
	event.CorrelationID = strings.TrimSpace(event.CorrelationID)
	if event.EventType == "" {
		return fmt.Errorf("rp usage event type is required")
	}
	if event.Subject == "" {
		return fmt.Errorf("rp usage subject is required")
	}
	if event.ClientID == "" {
		return fmt.Errorf("rp usage client_id is required")
	}
	if event.Source == "" {
		event.Source = "backend"
	}
	if event.OccurredAt.IsZero() {
		event.OccurredAt = time.Now()
	}
	if event.DedupeKey == "" {
		event.DedupeKey = buildRPUsageDedupeKey(event)
	}
	if event.Payload == nil {
		event.Payload = domain.JSONMap{}
	}
	return e.repo.Create(ctx, &event)
}

func buildRPUsageDedupeKey(event domain.RPUsageEvent) string {
	raw := strings.Join([]string{
		event.EventType,
		event.Subject,
		event.ClientID,
		event.SessionID,
		event.Source,
		event.CorrelationID,
		event.OccurredAt.UTC().Format("2006-01-02T15:04:05.000Z"),
	}, "|")
	sum := sha256.Sum256([]byte(raw))
	return hex.EncodeToString(sum[:])
}
