package repository

import (
	"context"
	"github.com/go-nunu/nunu-layout-advanced/internal/model"
	"time"
)

type GameShieldRepository interface {
	GetGameShieldById(ctx context.Context, id int64) (*model.GameShield, error)
	GetGameShieldDuplicateName(ctx context.Context, appName string, uid int) (int64, error)
	AddGameShield(ctx context.Context, gameShield *model.GameShield) error
	UpdateGameShield(ctx context.Context, gameShield *model.GameShield) error
	DeleteGameShield(ctx context.Context, ruleId int) error
	GetGameShieldIsBuy(ctx context.Context, uid int64) (int64, error)
	GetGameShieldNextduedate(ctx context.Context, uid int64, productID int) (string, error)
	GetGameShieldNameByDunName(ctx context.Context, appName string) (string, error)
	GetGameShieldHostIdByDunName(ctx context.Context, hostId string) (string, error)
	GetGameShieldRuleIdByAppName(ctx context.Context, appName string) (int, error)
	UpdateGameShieldByHostId(ctx context.Context, gameShield *model.GameShield) error
	GetGameShieldByHostId(ctx context.Context, hostId int) (*model.GameShield, error)
	GetHostById(ctx context.Context, id int) (string, error)
	GetSoonExpiredGameShields(ctx context.Context, daysThreshold int) ([]*model.GameShield, error)
	GetExpiredGameShields(ctx context.Context) ([]*model.GameShield, error)
	SyncExpireTimeFromHostNextDueDate(ctx context.Context, uid int, hostId int) error
	GetAllGameShield(ctx context.Context) ([]*model.GameShield, error)
}

func NewGameShieldRepository(
	repository *Repository,
) GameShieldRepository {
	return &gameShieldRepository{
		Repository: repository,
	}
}

type gameShieldRepository struct {
	*Repository
}

func (r *gameShieldRepository) GetGameShieldById(ctx context.Context, id int64) (*model.GameShield, error) {
	var res model.GameShield
	if err := r.DB(ctx).Where("id = ?", id).First(&res).Error; err != nil {
		return nil, err
	}
	return &res, nil
}

func (r *gameShieldRepository) GetGameShieldDuplicateName(ctx context.Context, appName string, uid int) (int64, error) {
	var count int64
	if err := r.DB(ctx).Model(&model.GameShield{}).Where("app_name = ?", appName).Where("uid = ?", uid).Count(&count).Error; err != nil {
		return 0, err
	}
	return count, nil
}

func (r *gameShieldRepository) AddGameShield(ctx context.Context, gameShield *model.GameShield) error {
	if err := r.DB(ctx).Create(gameShield).Error; err != nil {
		return err
	}
	return nil
}

func (r *gameShieldRepository) UpdateGameShield(ctx context.Context, gameShield *model.GameShield) error {
	if err := r.DB(ctx).Where("host_id = ?", gameShield.HostId).Updates(gameShield).Error; err != nil {
		return err
	}
	return nil
}

func (r *gameShieldRepository) DeleteGameShield(ctx context.Context, ruleId int) error {
	if err := r.DB(ctx).Where("rule_id = ?", ruleId).Delete(&model.GameShield{}).Error; err != nil {
		return err
	}
	return nil
}

func (r *gameShieldRepository) GetGameShieldIsBuy(ctx context.Context, uid int64) (int64, error) {
	var count int64
	if err := r.DB(ctx).Table("shd_host").
		Where("domainstatus = ?", "Active").
		Where("productid = ?", 67).
		Where("uid = ?", uid).
		Count(&count).Error; err != nil {
		return 0, err
	}
	return count, nil
}

func (r *gameShieldRepository) GetGameShieldNextduedate(ctx context.Context, uid int64, productID int) (string, error) {
	var nextDueDate string
	err := r.DB(ctx).Table("shd_host").
		Select("nextduedate").
		Where("id = ?", productID).
		Where("uid = ?", uid).
		Scan(&nextDueDate).Error

	if err != nil {
		return "", err
	}

	return nextDueDate, nil
}

func (r *gameShieldRepository) GetGameShieldNameByDunName(ctx context.Context, appName string) (string, error) {
	var res string
	if err := r.DB(ctx).Model(&model.GameShield{}).
		Where("app_name = ?", appName).
		Pluck("dun_name", &res).Error; err != nil {
		return "", err
	}
	return res, nil
}

func (r *gameShieldRepository) GetGameShieldHostIdByDunName(ctx context.Context, hostId string) (string, error) {
	var res string
	if err := r.DB(ctx).Model(&model.GameShield{}).
		Where("host_id = ?", hostId).
		Pluck("dun_name", &res).Error; err != nil {
		return "", err
	}
	return res, nil
}

func (r *gameShieldRepository) GetGameShieldRuleIdByAppName(ctx context.Context, appName string) (int, error) {
	var res int
	if err := r.DB(ctx).Model(&model.GameShield{}).
		Where("app_name = ?", appName).
		Pluck("rule_id", &res).Error; err != nil {
		return 0, err
	}
	return res, nil
}

func (r *gameShieldRepository) UpdateGameShieldByHostId(ctx context.Context, req *model.GameShield) error {
	if err := r.DB(ctx).Where("host_id = ?", req.HostId).Updates(req).Error; err != nil {
		return err
	}
	return nil
}

func (r *gameShieldRepository) GetGameShieldByHostId(ctx context.Context, hostId int) (*model.GameShield, error) {
	var res model.GameShield
	if err := r.DB(ctx).Where("host_id = ?", hostId).First(&res).Error; err != nil {
		return nil, err
	}
	return &res, nil
}

func (r *gameShieldRepository) GetHostById(ctx context.Context, id int) (string, error) {
	var res string
	if err := r.DB(ctx).Table("shd_host").
		Where("id = ?", id).
		Pluck("domain", &res).Error; err != nil {
		return "", err
	}
	return res, nil
}

// GetSoonExpiredGameShields 获取即将在指定天数内过期的记录
func (r *gameShieldRepository) GetSoonExpiredGameShields(ctx context.Context, daysThreshold int) ([]*model.GameShield, error) {
	var shields []*model.GameShield

	// 当前时间戳
	nowTimestamp := time.Now().Unix()

	// 计算N天后的时间戳
	futureTimestamp := nowTimestamp + int64(daysThreshold*24*60*60)

	// 查询即将到期的记录 (过期时间在当前时间和N天后之间)
	if err := r.DB(ctx).
		Where("expire_time > ? AND expire_time < ?", nowTimestamp, futureTimestamp).
		Find(&shields).Error; err != nil {
		return nil, err
	}

	return shields, nil
}

// GetExpiredGameShields 获取已过期的记录
func (r *gameShieldRepository) GetExpiredGameShields(ctx context.Context) ([]*model.GameShield, error) {
	var shields []*model.GameShield

	// 当前时间戳
	nowTimestamp := time.Now().Unix()

	// 查询已过期的记录（过期时间小于当前时间）
	if err := r.DB(ctx).
		Where("expire_time < ? AND expire_time != 0", nowTimestamp).
		Find(&shields).Error; err != nil {
		return nil, err
	}

	return shields, nil
}

// SyncExpireTimeFromHostNextDueDate 同步host表的nextduedate到game_shield表的ExpireTime
func (r *gameShieldRepository) SyncExpireTimeFromHostNextDueDate(ctx context.Context, uid int, hostId int) error {
	var nextduedate int64

	// 先从shd_host表获取nextduedate
	err := r.DB(ctx).Table("shd_host").
		Select("nextduedate").
		Where("id = ?", hostId).
		Where("uid = ?", uid).
		Scan(&nextduedate).Error

	if err != nil {
		return err
	}

	// 更新shd_game_shield表的ExpireTime
	return r.DB(ctx).Model(&model.GameShield{}).
		Where("host_id = ?", hostId).
		Where("uid = ?", uid).
		Update("expire_time", nextduedate).Error
}

func (r *gameShieldRepository) GetAllGameShield(ctx context.Context) ([]*model.GameShield, error) {
	var res []*model.GameShield
	if err := r.DB(ctx).Model(&model.GameShield{}).Find(&res).Error; err != nil {
		return nil, err
	}
	return res, nil
}
