package services

import (
	"NetworkAuth/database"
	"NetworkAuth/models"
	"fmt"
	"strconv"
	"time"

	"github.com/sirupsen/logrus"
)

// StartLogCleanupTask 启动日志清理定时任务
// 每天执行一次，且服务启动后也会尝试执行一次
func StartLogCleanupTask() {
	go func() {
		// 启动后延迟1分钟执行首次清理，避免影响启动速度
		time.Sleep(1 * time.Minute)
		cleanupLogs()

		// 每天执行一次
		ticker := time.NewTicker(24 * time.Hour)
		defer ticker.Stop()

		for range ticker.C {
			cleanupLogs()
		}
	}()
}

func cleanupLogs() {
	logrus.Debug("开始执行日志清理任务...")

	// 获取清理配置 (使用实时查询)
	loginLogDays := getSettingInt("login_log_cleanup_days", 30)
	loginLogLimit := getSettingInt("login_log_cleanup_limit", 10000)
	operationLogDays := getSettingInt("operation_log_cleanup_days", 30)
	operationLogLimit := getSettingInt("operation_log_cleanup_limit", 10000)

	// 清理登录日志
	if err := cleanupTable(&models.LoginLog{}, loginLogDays, loginLogLimit); err != nil {
		logrus.WithError(err).Error("清理登录日志失败")
	}

	// 清理操作日志
	if err := cleanupTable(&models.OperationLog{}, operationLogDays, operationLogLimit); err != nil {
		logrus.WithError(err).Error("清理操作日志失败")
	}

	// 清理刷新令牌（已过期的记录，包括已撤销的旧记录）
	refreshTokenDays := getSettingInt("refresh_token_cleanup_days", 7)
	if refreshTokenDays > 0 {
		if err := GetRefreshTokenService().CleanupExpired(refreshTokenDays); err != nil {
			logrus.WithError(err).Error("清理刷新令牌失败")
		} else {
			logrus.Debugf("清理刷新令牌完成 (保留 %d 天)", refreshTokenDays)
		}
	}

	logrus.Debug("日志清理任务执行完成")
}

// getSettingInt 获取配置整数值
func getSettingInt(key string, defaultValue int) int {
	setting, err := GetSettingsService().GetSettingRealtime(key)
	if err != nil {
		return defaultValue
	}

	val, err := strconv.Atoi(setting.Value)
	if err != nil {
		return defaultValue
	}
	return val
}

// cleanupTable 通用清理函数
func cleanupTable(model interface{}, retentionDays int, maxCount int) error {
	db, err := database.GetDB()
	if err != nil {
		return err
	}

	// 1. 按天清理
	if retentionDays > 0 {
		cutoffDate := time.Now().AddDate(0, 0, -retentionDays)
		result := db.Unscoped().Where("created_at < ?", cutoffDate).Delete(model)
		if result.Error != nil {
			return fmt.Errorf("按天清理失败: %w", result.Error)
		}
		if result.RowsAffected > 0 {
			logrus.Debugf("清理日志 (按天): 删除 %d 条记录", result.RowsAffected)
		}
	}

	// 2. 按数量清理
	if maxCount > 0 {
		count, err := CountEntitiesByCondition(model, "", db)
		if err != nil {
			return fmt.Errorf("查询总数失败: %w", err)
		}

		if count > int64(maxCount) {
			// 找出保留范围内的最后一条记录（第 maxCount 条，按时间倒序）
			var keepRecord struct {
				ID uint
			}

			// 假设 ID 是自增的主键，且 ID 越大代表记录越新
			if err := db.Model(model).Select("id").Order("id DESC").Offset(maxCount - 1).Limit(1).Scan(&keepRecord).Error; err != nil {
				return fmt.Errorf("查询分界记录失败: %w", err)
			}

			if keepRecord.ID > 0 {
				result := db.Unscoped().Where("id < ?", keepRecord.ID).Delete(model)
				if result.Error != nil {
					return fmt.Errorf("按数量清理失败: %w", result.Error)
				}
				if result.RowsAffected > 0 {
					logrus.Debugf("清理日志 (按数量): 删除 %d 条记录", result.RowsAffected)
				}
			}
		}
	}

	return nil
}
