package filterPoly

import (
	log "app.yhyue.com/moapp/jylog"
	"fmt"
	"time"
)

// IsWaitVerify 是否处于等待验证码校验
func (a *ReqFilterPoly) IsWaitVerify(k string) bool {
	return AllRedis.Get(fmt.Sprintf(WaitVerifyKey, k)) != nil
}

// SetWaitVerify 设置验证码
func (a *ReqFilterPoly) SetWaitVerify(k string, t int64) {
	AllRedis.Set(fmt.Sprintf(WaitVerifyKey, k), 1, t)
}

// ClearWaitVerify 清除验证码状态
func (a *ReqFilterPoly) ClearWaitVerify(k string) {
	AllRedis.Del(fmt.Sprintf(WaitVerifyKey, k))
	AllRedis.Del(fmt.Sprintf(VerifyRedisKey, k))
}

// VerifyErrDetail 验证码输入出错统计
func (a *ReqFilterPoly) VerifyErrDetail(k string) {
	if len(a.Rule.VcodeErrorTimes) != 2 {
		return
	}
	if !RateOk(fmt.Sprintf(ErrVerifyKey, k), a.Rule.VcodeErrorTimes[1], time.Duration(a.Rule.VcodeErrorTimes[0])*time.Second) {
		log.Infof("%s 验证码多次验证出错，加入临时黑名单", k)
		AllRedis.Del(fmt.Sprintf(ErrVerifyKey, k))
		a.addBackList(k, "exceed VerifyKey")
	}
}

// rateCheckOk 访问频率统计
func (a *ReqFilterPoly) rateCheckOk(k string, r []int64) bool {
	if len(r) != 2 {
		return true
	}
	ladder := r[0] //时间阶梯
	timers := r[1] //访问次数

	key := fmt.Sprintf(RateDataKey, a.Rule.Alias, ladder, k)
	flag := RateOk(key, timers, time.Duration(ladder)*time.Second)
	if !flag {
		AllRedis.Del(key)
	}
	return flag
}

// finalRateCheckOk 超出最大阈值，每n次弹出验证码
func (a *ReqFilterPoly) finalRateCheckOk(k string, r []int64, sign string) bool {
	if len(r) != 2 {
		return true
	}
	ladder := r[0] //时间阶梯
	timers := r[1] //访问次数
	key := fmt.Sprintf(RateDataKey, a.Rule.Alias, ladder, k)
	flag := RateOk(key, timers, time.Duration(ladder)*time.Second)

	if !flag { //超过阀值最大限制 根据请求频率显示验证码
		if sign == "id" {
			return !a.ShowCodeById(k)
		}
		return !a.ShowCodeByIp(k)
	}
	return flag
}

// RateOk 次数统计
func RateOk(keys string, count int64, duration time.Duration) bool {
	if AllRedis.IncrTimeout(keys, duration) >= count {
		return false
	}
	return true
}

// ShowCodeById 超出最大阈值，每n次弹出验证码
func (a *ReqFilterPoly) ShowCodeById(k string) bool {
	c := AllRedis.IncrTimeout(fmt.Sprintf(ExceedTimeKey, a.Rule.Alias, k), time.Duration(a.Rule.IdTimeRange)*time.Second) //超出阀值请求次数
	if (c-1)%a.Rule.IdFrep == 0 {
		return true
	}
	return false
}

// ShowCodeByIp 超出最大阈值，每n次弹出验证码
func (a *ReqFilterPoly) ShowCodeByIp(k string) bool {
	c := AllRedis.IncrTimeout(fmt.Sprintf(ExceedTimeKey, a.Rule.Alias, k), time.Duration(a.Rule.IpTimeRange)*time.Second) //超出阀值请求次数
	if (c-1)%a.Rule.IpFrep == 0 {
		return true
	}
	return false
}
