package models

import (
	"context"
	"time"

	"bsm/full/module/base/passport/internal/impl"
)

var (
	// 默认缓存TTL
	DefaultTTL = 30 * time.Minute
	// 用户信息缓存TTL
	UserCacheTTL = 1 * time.Hour
	// Token缓存TTL
	TokenCacheTTL = 24 * time.Hour
)

// GetAccountByCache 通过缓存获取账户信息
func GetAccountByCache(ctx context.Context, field, value string) (*PassportAccount, error) {
	var account *PassportAccount

	key := impl.RedisService.BuildKey("account", field, value)

	// 尝试从缓存获取
	err := impl.RedisService.Get(key, &account)
	if err == nil && account != nil {
		return account, nil
	}

	// 缓存未命中，从数据库获取
	account, err = GetPassportAccountByField(field, value)
	if err != nil {
		return nil, err
	}

	// 存入缓存
	err = impl.RedisService.Set(key, account, UserCacheTTL)
	return account, err
}

// GetUserDataByCache 通过缓存获取用户扩展数据
func GetUserDataByCache(ctx context.Context, passportID uint) (*PassportData, error) {
	var data *PassportData

	key := impl.RedisService.BuildKey("userdata", passportID)

	// 尝试从缓存获取
	err := impl.RedisService.Get(key, &data)
	if err == nil && data != nil {
		return data, nil
	}

	// 缓存未命中，从数据库获取
	err = impl.DBService.Where("passport_id = ?", passportID).First(&data).Error
	if err != nil {
		return nil, err
	}

	// 存入缓存
	err = impl.RedisService.Set(key, data, UserCacheTTL)
	return data, err
}

// GetUserTagsByCache 通过缓存获取用户标签
func GetUserTagsByCache(ctx context.Context, passportID uint) ([]*PassportTags, error) {
	var tags []*PassportTags

	key := impl.RedisService.BuildKey("usertags", passportID)

	// 尝试从缓存获取
	err := impl.RedisService.Get(key, &tags)
	if err == nil && tags != nil {
		return tags, nil
	}

	// 缓存未命中，从数据库获取
	err = impl.DBService.Where("passport_id = ?", passportID).Find(&tags).Error
	if err != nil {
		return nil, err
	}

	// 存入缓存
	err = impl.RedisService.Set(key, tags, DefaultTTL)
	return tags, err
}

// InvalidateUserCache 清除用户相关缓存
func InvalidateUserCache(ctx context.Context, passportID uint, identity string) error {
	keys := []string{
		impl.RedisService.BuildKey("account", "id", passportID),
		impl.RedisService.BuildKey("account", "identity", identity),
		impl.RedisService.BuildKey("userdata", passportID),
		impl.RedisService.BuildKey("usertags", passportID),
	}

	for _, key := range keys {
		impl.RedisService.Client.Del(impl.RedisService.Ctx, key)
	}

	return nil
}

// SetTokenCache 设置Token缓存
func SetTokenCache(ctx context.Context, identity, token string) error {
	key := impl.RedisService.BuildKey("token", identity)
	return impl.RedisService.Set(key, token, TokenCacheTTL)
}

// GetTokenCache 获取Token缓存
func GetTokenCache(ctx context.Context, identity string) (string, error) {
	var token string
	key := impl.RedisService.BuildKey("token", identity)
	err := impl.RedisService.Get(key, &token)
	return token, err
}

// InvalidateTokenCache 清除Token缓存
func InvalidateTokenCache(ctx context.Context, identity string) error {
	key := impl.RedisService.BuildKey("token", identity)
	return impl.RedisService.Client.Del(impl.RedisService.Ctx, key).Err()
}

// SetVerificationCodeCache 设置验证码缓存
func SetVerificationCodeCache(ctx context.Context, phone, code string, ttl time.Duration) error {
	key := impl.RedisService.BuildKey("verifycode", phone)
	return impl.RedisService.Set(key, code, ttl)
}

// GetVerificationCodeCache 获取验证码缓存
func GetVerificationCodeCache(ctx context.Context, phone string) (string, error) {
	var code string
	key := impl.RedisService.BuildKey("verifycode", phone)
	err := impl.RedisService.Get(key, &code)
	return code, err
}

// InvalidateVerificationCodeCache 清除验证码缓存
func InvalidateVerificationCodeCache(ctx context.Context, phone string) error {
	key := impl.RedisService.BuildKey("verifycode", phone)
	return impl.RedisService.Client.Del(impl.RedisService.Ctx, key).Err()
}

// IncrementLoginAttempts 增加登录尝试次数
func IncrementLoginAttempts(ctx context.Context, account string) (int64, error) {
	key := impl.RedisService.BuildKey("loginattempts", account)
	result := impl.RedisService.Client.Incr(impl.RedisService.Ctx, key)
	if result.Err() != nil {
		return 0, result.Err()
	}

	// 设置过期时间（15分钟）
	impl.RedisService.Client.Expire(impl.RedisService.Ctx, key, 15*time.Minute)

	return result.Val(), nil
}

// GetLoginAttempts 获取登录尝试次数
func GetLoginAttempts(ctx context.Context, account string) (int64, error) {
	key := impl.RedisService.BuildKey("loginattempts", account)
	result := impl.RedisService.Client.Get(impl.RedisService.Ctx, key)
	if result.Err() != nil {
		return 0, nil // 如果key不存在，返回0
	}
	return result.Int64()
}

// ClearLoginAttempts 清除登录尝试次数
func ClearLoginAttempts(ctx context.Context, account string) error {
	key := impl.RedisService.BuildKey("loginattempts", account)
	return impl.RedisService.Client.Del(impl.RedisService.Ctx, key).Err()
}
