package securityevents

import (
	"context"
	"time"

	"github.com/easyai/easyai-ai-gateway/apps/api/internal/store"
)

const (
	defaultSecurityEventRetirementDuration = 6 * time.Minute
	securityEventRetirementWorkerInterval  = time.Minute
)

type SecurityEventRetirementRepository interface {
	SecurityEventConnection(context.Context) (store.SecurityEventConnection, error)
	FinalizeRetiringSecurityEventConnection(context.Context, string, int64) error
}

// RunSecurityEventRetirementWorker owns the local end of SSF retirement at the
// server lifecycle. It intentionally does not share an Active identity
// Runtime's context, because that Runtime is closed before the RFC 8935 overlap
// period expires. Store-level generation CAS makes one worker per replica safe.
func RunSecurityEventRetirementWorker(ctx context.Context, repository SecurityEventRetirementRepository) {
	runSecurityEventRetirementWorker(
		ctx,
		repository,
		defaultSecurityEventRetirementDuration,
		securityEventRetirementWorkerInterval,
	)
}

func runSecurityEventRetirementWorker(
	ctx context.Context,
	repository SecurityEventRetirementRepository,
	retirementDuration time.Duration,
	interval time.Duration,
) {
	if repository == nil {
		return
	}
	if retirementDuration <= 0 {
		retirementDuration = defaultSecurityEventRetirementDuration
	}
	if interval <= 0 {
		interval = securityEventRetirementWorkerInterval
	}
	ticker := time.NewTicker(interval)
	defer ticker.Stop()
	for {
		finalizeDueSecurityEventRetirement(ctx, repository, retirementDuration)
		select {
		case <-ctx.Done():
			return
		case <-ticker.C:
		}
	}
}

func finalizeDueSecurityEventRetirement(
	ctx context.Context,
	repository SecurityEventRetirementRepository,
	retirementDuration time.Duration,
) {
	connection, err := repository.SecurityEventConnection(ctx)
	if err != nil || connection.LifecycleStatus != "retiring" {
		return
	}
	if retirementDuration <= 0 {
		retirementDuration = defaultSecurityEventRetirementDuration
	}
	if time.Since(connection.UpdatedAt) < retirementDuration {
		return
	}
	// Finalization atomically queues every Secret reference and removes only the
	// exact retiring generation. A concurrent worker or changed generation is a
	// benign CAS miss and will be observed on the next loop.
	_ = repository.FinalizeRetiringSecurityEventConnection(ctx, connection.ConnectionID, connection.Version)
}
