package scheduler

import (
	"context"
	"time"

	"github.com/robfig/cron/v3"
	"go.uber.org/zap"

	"codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/config"
	"codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/pkg/leaderelection"
	"codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/internal/service/ipcleanup"
)

// IPCleanupScheduler handles scheduled IP address cleanup for GDPR compliance
// CWE-359: IP addresses must be deleted after 90 days
type IPCleanupScheduler struct {
	cron            *cron.Cron
	cleanupService  *ipcleanup.CleanupService
	leaderElection  leaderelection.LeaderElection
	logger          *zap.Logger
	enabled         bool
	schedulePattern string
}

// ProvideIPCleanupScheduler creates a new IPCleanupScheduler from config
func ProvideIPCleanupScheduler(
	cfg *config.Config,
	cleanupService *ipcleanup.CleanupService,
	leaderElection leaderelection.LeaderElection,
	logger *zap.Logger,
) *IPCleanupScheduler {
	// IP cleanup enabled if configured (defaults to true for GDPR compliance)
	enabled := cfg.Scheduler.IPCleanupEnabled
	// Default: run daily at 2 AM
	schedulePattern := cfg.Scheduler.IPCleanupSchedule

	// Create cron with logger
	cronLog := &cronLogger{logger: logger.Named("cron")}
	c := cron.New(
		cron.WithLogger(cronLog),
		cron.WithChain(
			cron.Recover(cronLog),
		),
	)

	return &IPCleanupScheduler{
		cron:            c,
		cleanupService:  cleanupService,
		leaderElection:  leaderElection,
		logger:          logger.Named("ip-cleanup-scheduler"),
		enabled:         enabled,
		schedulePattern: schedulePattern,
	}
}

// Start starts the IP cleanup scheduler
func (s *IPCleanupScheduler) Start() error {
	if !s.enabled {
		s.logger.Info("IP cleanup scheduler is disabled")
		return nil
	}

	s.logger.Info("starting IP cleanup scheduler for GDPR compliance",
		zap.String("schedule", s.schedulePattern),
		zap.String("retention_period", "90 days"))

	// Schedule the IP cleanup job
	_, err := s.cron.AddFunc(s.schedulePattern, s.cleanupIPs)
	if err != nil {
		s.logger.Error("failed to schedule IP cleanup job", zap.Error(err))
		return err
	}

	// Start the cron scheduler
	s.cron.Start()

	s.logger.Info("IP cleanup scheduler started successfully")
	return nil
}

// Stop stops the IP cleanup scheduler
func (s *IPCleanupScheduler) Stop() {
	if !s.enabled {
		return
	}

	s.logger.Info("stopping IP cleanup scheduler")
	ctx := s.cron.Stop()
	<-ctx.Done()
	s.logger.Info("IP cleanup scheduler stopped")
}

// cleanupIPs is the cron job function that cleans up expired IP addresses
func (s *IPCleanupScheduler) cleanupIPs() {
	// Only execute if this instance is the leader
	if !s.leaderElection.IsLeader() {
		s.logger.Debug("skipping IP cleanup - not the leader instance",
			zap.String("instance_id", s.leaderElection.GetInstanceID()))
		return
	}

	s.logger.Info("executing scheduled IP cleanup for GDPR compliance as leader instance",
		zap.String("instance_id", s.leaderElection.GetInstanceID()))

	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
	defer cancel()

	err := s.cleanupService.CleanupExpiredIPs(ctx)
	if err != nil {
		s.logger.Error("IP cleanup failed", zap.Error(err))
		return
	}

	s.logger.Info("IP cleanup completed successfully")
}
