package utils

import (
	"errors"
	"math/rand"
	"strconv"
	"strings"
	"time"
)

type cap struct {
	Phone   string
	Captcha string
	Expire  time.Time
}

// CaptchaEngine 验证码引擎
type CaptchaEngine struct {
	capList map[string]cap
}

var capEngine *CaptchaEngine

// NewCaptchaEngine 创建验证码引擎
func NewCaptchaEngine() *CaptchaEngine {
	return &CaptchaEngine{
		capList: make(map[string]cap),
	}
}

// SendCaptcha 发送验证码
func SendCaptcha(phone string) error {
	if phone == "" {
		return errors.New("验证码发送错误: 没有手机号")
	}

	capEngine.SendCaptcha(phone)
	return nil
}

// ValidCaptcha 校验 验证码
func ValidCaptcha(phone, cap string) error {
	if phone == "" {
		return errors.New("验证码校验失败: 没有手机号")
	}

	return capEngine.ValidCaptcha(phone, cap)
}

// Random 获取随机数
// 连续调用会有随机数不随机问题
func (c *CaptchaEngine) Random(length int, phone string) string {
	phoneInt, _ := strconv.ParseInt(phone, 10, 64)

	r := rand.New(rand.NewSource(time.Now().UnixNano() + phoneInt))
	dict := strings.Split("0123456789", "")

	res := ""
	for i := 0; i < length; i++ {
		res = res + dict[r.Intn(10)]
	}

	return res
}

// SendCaptcha 发送验证码
func (c *CaptchaEngine) SendCaptcha(phone string) {
	theCap := cap{
		Phone:   phone,
		Captcha: capEngine.Random(6, phone),
		Expire:  time.Now().Local().Add(1 * time.Minute),
	}

	c.capList[phone] = theCap

	LogError("验证码 - " + phone + " : " + theCap.Captcha)

	SendSMS("captcha", theCap.Phone, theCap.Captcha)
}

// ValidCaptcha 验证 验证码
func (c *CaptchaEngine) ValidCaptcha(phone, cap string) error {
	theCap, ok := c.capList[phone]
	if !ok {
		return errors.New("手机号无效或验证码已过期")
	}

	if time.Now().Local().After(theCap.Expire) {
		// 注销
		delete(c.capList, phone)

		return errors.New("验证码已过期")
	}

	if theCap.Captcha != cap {
		return errors.New("验证码不正确")
	}

	// 如果成功, 则注销
	delete(c.capList, phone)

	return nil
}

func init() {
	capEngine = NewCaptchaEngine()
}
