package captcha

import (
	"context"
	"time"

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

// Config 验证码配置
type Config struct {
	KeyLong            int
	ImgWidth           int
	ImgHeight          int
	OpenCaptcha        int // 0-关闭 1-开启
	OpenCaptchaTimeout int // 验证码超时时间(秒)
}

// Captcha 验证码
type Captcha struct {
	config Config
	store  base64Captcha.Store
}

// RedisStore Redis存储
type RedisStore struct {
	client     redis.UniversalClient
	expiration time.Duration
	prefix     string
}

// NewRedisStore 创建Redis存储
func NewRedisStore(client redis.UniversalClient, expiration time.Duration) *RedisStore {
	return &RedisStore{
		client:     client,
		expiration: expiration,
		prefix:     "captcha:",
	}
}

func (s *RedisStore) Set(id string, value string) error {
	return s.client.Set(context.Background(), s.prefix+id, value, s.expiration).Err()
}

func (s *RedisStore) Get(id string, clear bool) string {
	ctx := context.Background()
	key := s.prefix + id
	val, err := s.client.Get(ctx, key).Result()
	if err != nil {
		return ""
	}
	if clear {
		s.client.Del(ctx, key)
	}
	return val
}

func (s *RedisStore) Verify(id, answer string, clear bool) bool {
	v := s.Get(id, clear)
	return v == answer
}

// NewCaptcha 创建验证码实例
func NewCaptcha(config Config, store base64Captcha.Store) *Captcha {
	if store == nil {
		store = base64Captcha.DefaultMemStore
	}
	return &Captcha{
		config: config,
		store:  store,
	}
}

// Generate 生成验证码
func (c *Captcha) Generate() (id, b64s, answer string, err error) {
	driver := base64Captcha.NewDriverDigit(
		c.config.ImgHeight,
		c.config.ImgWidth,
		c.config.KeyLong,
		0.7,
		80,
	)
	cp := base64Captcha.NewCaptcha(driver, c.store)
	return cp.Generate()
}

// Verify 验证验证码
func (c *Captcha) Verify(id, answer string, clear bool) bool {
	return c.store.Verify(id, answer, clear)
}

// IsOpen 是否开启验证码
func (c *Captcha) IsOpen() bool {
	return c.config.OpenCaptcha > 0
}
