package system

import (
	"context"

	"github.com/redis/go-redis/v9"
)

// JwtBlacklist JWT黑名单实体
type JwtBlacklist struct {
	ID  uint
	Jwt string
}

// JwtBlacklistRepo JWT黑名单仓储接口
type JwtBlacklistRepo interface {
	Create(ctx context.Context, jwt string) error
	IsInBlacklist(ctx context.Context, jwt string) bool
	LoadAll(ctx context.Context) ([]string, error)
	GetRedisJWT(ctx context.Context, username string) (string, error)
	SetRedisJWT(ctx context.Context, token, username string) error
}

// JwtBlacklistUsecase JWT黑名单用例
type JwtBlacklistUsecase struct {
	repo  JwtBlacklistRepo
	cache map[string]struct{} // 内存缓存
}

// NewJwtBlacklistUsecase 创建JWT黑名单用例
func NewJwtBlacklistUsecase(repo JwtBlacklistRepo) *JwtBlacklistUsecase {
	uc := &JwtBlacklistUsecase{
		repo:  repo,
		cache: make(map[string]struct{}),
	}
	// 加载黑名单到缓存
	uc.LoadAll(context.Background())
	return uc
}

// JoinBlacklist 加入黑名单
func (uc *JwtBlacklistUsecase) JoinBlacklist(ctx context.Context, jwt string) error {
	if err := uc.repo.Create(ctx, jwt); err != nil {
		return err
	}
	uc.cache[jwt] = struct{}{}
	return nil
}

// JsonInBlacklist JWT加入黑名单（GVA兼容方法名）
func (uc *JwtBlacklistUsecase) JsonInBlacklist(ctx context.Context, jwt string) error {
	return uc.JoinBlacklist(ctx, jwt)
}

// IsInBlacklist 检查是否在黑名单中
func (uc *JwtBlacklistUsecase) IsInBlacklist(jwt string) bool {
	_, ok := uc.cache[jwt]
	return ok
}

// IsBlacklist 检查是否在黑名单中（GVA兼容方法名）
func (uc *JwtBlacklistUsecase) IsBlacklist(ctx context.Context, jwt string) bool {
	return uc.IsInBlacklist(jwt)
}

// LoadAll 加载所有黑名单到缓存
func (uc *JwtBlacklistUsecase) LoadAll(ctx context.Context) error {
	jwts, err := uc.repo.LoadAll(ctx)
	if err != nil {
		return err
	}
	for _, jwt := range jwts {
		uc.cache[jwt] = struct{}{}
	}
	return nil
}

// GetRedisJWT 从Redis获取JWT
func (uc *JwtBlacklistUsecase) GetRedisJWT(ctx context.Context, username string) (string, error) {
	if uc.repo == nil {
		return "", redis.Nil
	}
	return uc.repo.GetRedisJWT(ctx, username)
}

// SetRedisJWT 设置Redis JWT
func (uc *JwtBlacklistUsecase) SetRedisJWT(ctx context.Context, token, username string) error {
	if uc.repo == nil {
		return nil
	}
	return uc.repo.SetRedisJWT(ctx, token, username)
}
