package postgres

import (
	"context"
	"time"

	"gorm.io/gorm"

	"github.com/break/junhong_cmp_fiber/internal/model"
)

// DataCleanupConfigStore 数据清理配置存储
type DataCleanupConfigStore struct {
	db *gorm.DB
}

// NewDataCleanupConfigStore 创建数据清理配置存储实例
func NewDataCleanupConfigStore(db *gorm.DB) *DataCleanupConfigStore {
	return &DataCleanupConfigStore{db: db}
}

// Create 创建清理配置
func (s *DataCleanupConfigStore) Create(ctx context.Context, config *model.DataCleanupConfig) error {
	return s.db.WithContext(ctx).Create(config).Error
}

// GetByID 根据ID获取清理配置
func (s *DataCleanupConfigStore) GetByID(ctx context.Context, id uint) (*model.DataCleanupConfig, error) {
	var config model.DataCleanupConfig
	if err := s.db.WithContext(ctx).First(&config, id).Error; err != nil {
		return nil, err
	}
	return &config, nil
}

// GetByTableName 根据表名获取清理配置
func (s *DataCleanupConfigStore) GetByTableName(ctx context.Context, tableName string) (*model.DataCleanupConfig, error) {
	var config model.DataCleanupConfig
	if err := s.db.WithContext(ctx).Where("table_name = ?", tableName).First(&config).Error; err != nil {
		return nil, err
	}
	return &config, nil
}

// List 获取所有清理配置
func (s *DataCleanupConfigStore) List(ctx context.Context) ([]*model.DataCleanupConfig, error) {
	var configs []*model.DataCleanupConfig
	if err := s.db.WithContext(ctx).Order("id ASC").Find(&configs).Error; err != nil {
		return nil, err
	}
	return configs, nil
}

// ListEnabled 获取启用的清理配置
func (s *DataCleanupConfigStore) ListEnabled(ctx context.Context) ([]*model.DataCleanupConfig, error) {
	var configs []*model.DataCleanupConfig
	if err := s.db.WithContext(ctx).Where("enabled = 1").Order("id ASC").Find(&configs).Error; err != nil {
		return nil, err
	}
	return configs, nil
}

// Update 更新清理配置
func (s *DataCleanupConfigStore) Update(ctx context.Context, config *model.DataCleanupConfig) error {
	return s.db.WithContext(ctx).Save(config).Error
}

// Delete 删除清理配置
func (s *DataCleanupConfigStore) Delete(ctx context.Context, id uint) error {
	return s.db.WithContext(ctx).Delete(&model.DataCleanupConfig{}, id).Error
}

// DataCleanupLogStore 数据清理日志存储
type DataCleanupLogStore struct {
	db *gorm.DB
}

// NewDataCleanupLogStore 创建数据清理日志存储实例
func NewDataCleanupLogStore(db *gorm.DB) *DataCleanupLogStore {
	return &DataCleanupLogStore{db: db}
}

// Create 创建清理日志
func (s *DataCleanupLogStore) Create(ctx context.Context, log *model.DataCleanupLog) error {
	return s.db.WithContext(ctx).Create(log).Error
}

// GetByID 根据ID获取清理日志
func (s *DataCleanupLogStore) GetByID(ctx context.Context, id uint) (*model.DataCleanupLog, error) {
	var log model.DataCleanupLog
	if err := s.db.WithContext(ctx).First(&log, id).Error; err != nil {
		return nil, err
	}
	return &log, nil
}

// Update 更新清理日志
func (s *DataCleanupLogStore) Update(ctx context.Context, log *model.DataCleanupLog) error {
	return s.db.WithContext(ctx).Save(log).Error
}

// List 分页获取清理日志
func (s *DataCleanupLogStore) List(ctx context.Context, page, pageSize int, tableName string) ([]*model.DataCleanupLog, int64, error) {
	var logs []*model.DataCleanupLog
	var total int64

	query := s.db.WithContext(ctx).Model(&model.DataCleanupLog{})
	if tableName != "" {
		query = query.Where("table_name = ?", tableName)
	}

	if err := query.Count(&total).Error; err != nil {
		return nil, 0, err
	}

	offset := (page - 1) * pageSize
	if err := query.Order("started_at DESC").Offset(offset).Limit(pageSize).Find(&logs).Error; err != nil {
		return nil, 0, err
	}

	return logs, total, nil
}

// GetLatestRunning 获取正在运行的清理任务
func (s *DataCleanupLogStore) GetLatestRunning(ctx context.Context, tableName string) (*model.DataCleanupLog, error) {
	var log model.DataCleanupLog
	if err := s.db.WithContext(ctx).Where("table_name = ? AND status = 'running'", tableName).First(&log).Error; err != nil {
		return nil, err
	}
	return &log, nil
}

// DeleteOldRecords 删除指定表的过期记录
// 返回删除的记录数
func (s *DataCleanupLogStore) DeleteOldRecords(ctx context.Context, tableName string, retentionDays int, batchSize int) (int64, error) {
	cutoffTime := time.Now().AddDate(0, 0, -retentionDays)

	// 根据表名执行不同的删除逻辑
	var result *gorm.DB
	switch tableName {
	case "tb_polling_alert_history":
		result = s.db.WithContext(ctx).
			Where("created_at < ?", cutoffTime).
			Limit(batchSize).
			Delete(&model.PollingAlertHistory{})
	case "tb_data_cleanup_log":
		result = s.db.WithContext(ctx).
			Where("started_at < ?", cutoffTime).
			Limit(batchSize).
			Delete(&model.DataCleanupLog{})
	case "tb_polling_manual_trigger_log":
		result = s.db.WithContext(ctx).
			Where("triggered_at < ?", cutoffTime).
			Limit(batchSize).
			Delete(&model.PollingManualTriggerLog{})
	default:
		// 对于其他表，使用原始 SQL
		result = s.db.WithContext(ctx).Exec(
			"DELETE FROM "+tableName+" WHERE created_at < ? LIMIT ?",
			cutoffTime, batchSize,
		)
	}

	if result.Error != nil {
		return 0, result.Error
	}
	return result.RowsAffected, nil
}

// CountOldRecords 统计指定表的过期记录数
func (s *DataCleanupLogStore) CountOldRecords(ctx context.Context, tableName string, retentionDays int) (int64, error) {
	cutoffTime := time.Now().AddDate(0, 0, -retentionDays)

	var count int64
	// 根据表名查询不同的时间字段
	switch tableName {
	case "tb_polling_alert_history":
		if err := s.db.WithContext(ctx).Model(&model.PollingAlertHistory{}).
			Where("created_at < ?", cutoffTime).
			Count(&count).Error; err != nil {
			return 0, err
		}
	case "tb_data_cleanup_log":
		if err := s.db.WithContext(ctx).Model(&model.DataCleanupLog{}).
			Where("started_at < ?", cutoffTime).
			Count(&count).Error; err != nil {
			return 0, err
		}
	case "tb_polling_manual_trigger_log":
		if err := s.db.WithContext(ctx).Model(&model.PollingManualTriggerLog{}).
			Where("triggered_at < ?", cutoffTime).
			Count(&count).Error; err != nil {
			return 0, err
		}
	default:
		// 对于其他表，使用原始 SQL（使用 GORM 的 Scan 避免 Row() 返回 nil 导致 panic）
		if err := s.db.WithContext(ctx).Raw(
			"SELECT COUNT(*) FROM "+tableName+" WHERE created_at < ?",
			cutoffTime,
		).Scan(&count).Error; err != nil {
			return 0, err
		}
	}

	return count, nil
}
