package workers

import (
	"context"
	"time"

	"veza-backend-api/internal/services"

	"go.uber.org/zap"
	"gorm.io/gorm"
)

// PlaybackRetentionWorker gère l'exécution périodique de la politique de rétention
// T0382: Create Playback Analytics Data Retention Policy
type PlaybackRetentionWorker struct {
	db               *gorm.DB
	retentionService *services.PlaybackRetentionPolicyService
	logger           *zap.Logger
	interval         time.Duration // Intervalle d'exécution
	policy           *services.RetentionPolicy
	stopChan         chan struct{}
	running          bool
}

// NewPlaybackRetentionWorker crée un nouveau worker de rétention
func NewPlaybackRetentionWorker(
	db *gorm.DB,
	retentionService *services.PlaybackRetentionPolicyService,
	logger *zap.Logger,
	interval time.Duration,
) *PlaybackRetentionWorker {
	if logger == nil {
		logger = zap.NewNop()
	}
	if interval <= 0 {
		interval = 24 * time.Hour // Par défaut, exécuter quotidiennement
	}

	return &PlaybackRetentionWorker{
		db:               db,
		retentionService: retentionService,
		logger:           logger,
		interval:         interval,
		policy:           services.DefaultRetentionPolicy(),
		stopChan:         make(chan struct{}),
		running:          false,
	}
}

// SetPolicy définit la politique de rétention à utiliser
func (w *PlaybackRetentionWorker) SetPolicy(policy *services.RetentionPolicy) {
	if policy != nil {
		w.policy = policy
	}
}

// Start démarre le worker de rétention
// T0382: Create Playback Analytics Data Retention Policy
func (w *PlaybackRetentionWorker) Start(ctx context.Context) {
	if w.running {
		w.logger.Warn("Retention worker is already running")
		return
	}

	w.running = true
	w.logger.Info("Starting playback retention worker",
		zap.Duration("interval", w.interval),
		zap.Duration("archive_after", w.policy.ArchiveAfter),
		zap.Duration("delete_after", w.policy.DeleteAfter))

	// Exécuter immédiatement au démarrage
	go w.runRetentionPolicy(ctx)

	// Puis exécuter périodiquement
	ticker := time.NewTicker(w.interval)
	defer ticker.Stop()

	for {
		select {
		case <-ctx.Done():
			w.logger.Info("Stopping playback retention worker")
			w.running = false
			return

		case <-w.stopChan:
			w.logger.Info("Stopping playback retention worker (stop requested)")
			w.running = false
			return

		case <-ticker.C:
			go w.runRetentionPolicy(ctx)
		}
	}
}

// Stop arrête le worker de rétention
func (w *PlaybackRetentionWorker) Stop() {
	if !w.running {
		return
	}
	close(w.stopChan)
}

// runRetentionPolicy exécute la politique de rétention
func (w *PlaybackRetentionWorker) runRetentionPolicy(ctx context.Context) {
	logger := w.logger.With(zap.String("worker", "playback_retention"))

	logger.Info("Running playback retention policy")

	// Créer un contexte avec timeout pour éviter les blocages
	retentionCtx, cancel := context.WithTimeout(ctx, 1*time.Hour)
	defer cancel()

	// Appliquer la politique de rétention
	if err := w.retentionService.ApplyRetentionPolicy(retentionCtx, w.policy); err != nil {
		logger.Error("Failed to apply retention policy",
			zap.Error(err))
		return
	}

	logger.Info("Playback retention policy applied successfully")
}

// IsRunning retourne si le worker est en cours d'exécution
func (w *PlaybackRetentionWorker) IsRunning() bool {
	return w.running
}
