package scheduler

import (
	"fmt"
	"log"
	"time"

	"verification-platform-backend/internal/database"
	"verification-platform-backend/internal/model"
)

type CleanupConfig struct {
	EnableAutoCleanup     bool
	CleanupIntervalHours  int
	CaptchaRetentionDays  int
	VerifyCodeRetentionDays int
	ApiUsageRetentionDays int
	WebhookLogRetentionDays int
	DeviceSessionRetentionDays int
}

var defaultConfig = CleanupConfig{
	EnableAutoCleanup:       false,
	CleanupIntervalHours:    24,
	CaptchaRetentionDays:    1,
	VerifyCodeRetentionDays: 7,
	ApiUsageRetentionDays:   30,
	WebhookLogRetentionDays: 30,
	DeviceSessionRetentionDays: 7,
}

func GetCleanupConfig() CleanupConfig {
	cfg := defaultConfig

	var settings []model.Setting
	database.DB.Where("category = ?", "cleanup").Find(&settings)

	for _, s := range settings {
		switch s.Key {
		case "enable_auto_cleanup":
			cfg.EnableAutoCleanup = s.Value == "true"
		case "cleanup_interval_hours":
			cfg.CleanupIntervalHours = parseVal(s.Value, defaultConfig.CleanupIntervalHours)
		case "captcha_retention_days":
			cfg.CaptchaRetentionDays = parseVal(s.Value, defaultConfig.CaptchaRetentionDays)
		case "verify_code_retention_days":
			cfg.VerifyCodeRetentionDays = parseVal(s.Value, defaultConfig.VerifyCodeRetentionDays)
		case "api_usage_retention_days":
			cfg.ApiUsageRetentionDays = parseVal(s.Value, defaultConfig.ApiUsageRetentionDays)
		case "webhook_log_retention_days":
			cfg.WebhookLogRetentionDays = parseVal(s.Value, defaultConfig.WebhookLogRetentionDays)
		case "device_session_retention_days":
			cfg.DeviceSessionRetentionDays = parseVal(s.Value, defaultConfig.DeviceSessionRetentionDays)
		}
	}

	return cfg
}

func parseVal(value string, defaultVal int) int {
	if value == "" {
		return defaultVal
	}
	var result int
	if _, err := fmt.Sscanf(value, "%d", &result); err != nil || result <= 0 {
		return defaultVal
	}
	return result
}

func StartCleanupScheduler() {
	go func() {
		for {
			cfg := GetCleanupConfig()
			interval := time.Duration(cfg.CleanupIntervalHours) * time.Hour
			if interval < time.Hour {
				interval = time.Hour
			}
			time.Sleep(interval)

			if !cfg.EnableAutoCleanup {
				continue
			}

			RunCleanup(cfg)
		}
	}()
	log.Println("[Scheduler] Cleanup scheduler started")
}

func RunCleanup(cfg CleanupConfig) {
	now := time.Now()
	totalCleaned := 0

	if cfg.CaptchaRetentionDays > 0 {
		cutoff := now.AddDate(0, 0, -cfg.CaptchaRetentionDays)
		result := database.DB.Where("expires_at < ?", cutoff).Delete(&model.Captcha{})
		if result.RowsAffected > 0 {
			log.Printf("[Cleanup] Deleted %d expired captchas", result.RowsAffected)
			totalCleaned += int(result.RowsAffected)
		}
	}

	if cfg.VerifyCodeRetentionDays > 0 {
		cutoff := now.AddDate(0, 0, -cfg.VerifyCodeRetentionDays)
		emailResult := database.DB.Where("expires_at < ? AND used = ?", cutoff, true).Delete(&model.EmailVerifyCode{})
		smsResult := database.DB.Where("expires_at < ? AND used = ?", cutoff, true).Delete(&model.SmsVerifyCode{})
		count := emailResult.RowsAffected + smsResult.RowsAffected
		if count > 0 {
			log.Printf("[Cleanup] Deleted %d expired verify codes", count)
			totalCleaned += int(count)
		}
	}

	if cfg.ApiUsageRetentionDays > 0 {
		cutoff := now.AddDate(0, 0, -cfg.ApiUsageRetentionDays)
		result := database.DB.Where("created_at < ?", cutoff).Delete(&model.ApiUsage{})
		if result.RowsAffected > 0 {
			log.Printf("[Cleanup] Deleted %d old api usage records", result.RowsAffected)
			totalCleaned += int(result.RowsAffected)
		}
	}

	if cfg.WebhookLogRetentionDays > 0 {
		cutoff := now.AddDate(0, 0, -cfg.WebhookLogRetentionDays)
		result := database.DB.Where("created_at < ?", cutoff).Delete(&model.WebhookLog{})
		if result.RowsAffected > 0 {
			log.Printf("[Cleanup] Deleted %d old webhook logs", result.RowsAffected)
			totalCleaned += int(result.RowsAffected)
		}
	}

	if cfg.DeviceSessionRetentionDays > 0 {
		cutoff := now.AddDate(0, 0, -cfg.DeviceSessionRetentionDays)
		result := database.DB.Where("last_heartbeat < ? AND last_heartbeat IS NOT NULL", cutoff).Delete(&model.DeviceSession{})
		if result.RowsAffected > 0 {
			log.Printf("[Cleanup] Deleted %d expired device sessions", result.RowsAffected)
			totalCleaned += int(result.RowsAffected)
		}
	}

	if totalCleaned > 0 {
		log.Printf("[Cleanup] Total cleaned: %d records", totalCleaned)
	}
}
