package app

import (
	"encoding/json"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"
	"time"

	"github.com/33cn/chain33/common/address"
	_ "github.com/33cn/chain33/system/address"
	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
	"gorm.io/gorm"
	"courseSign/server/global"
	"courseSign/server/model/airDrop"
	application "courseSign/server/model/app"
	"courseSign/server/model/common/response"
	"courseSign/server/model/user"
	"courseSign/server/service"
	"courseSign/server/utils"
	"courseSign/server/utils/errno"
)

var fileUploadAndDownloadService = service.ServiceGroupApp.ExampleServiceGroup.FileUploadAndDownloadService
var redPackageService = service.ServiceGroupApp.AirDropServiceGroup.RedPackageService
type VerificationApi struct{}

// Recaptcha 验证 通过直接分配红包
// @Tags Recaptcha
// @Summary 验证码 通过直接领取红包
// @accept application/json
// @Produce application/json
// @Param data body application.RecaptchaAndDrawRequest true "验证码 通过直接领取红包"
// @Success 200
// @Router /verification/recaptcha [post]
func (s *VerificationApi) Recaptcha(ctx *gin.Context) {
	var recaptcha application.RecaptchaAndDrawRequest
	_ = ctx.ShouldBindJSON(&recaptcha)
	if err := utils.Verify(recaptcha, utils.AddressVerify); err != nil {
		global.GVA_LOG.Error("Recaptcha verify err",zap.Error(err))
		response.FailWithMessage(err.Error(), ctx)
		return
	}
	if global.GVA_CONFIG.Recaptcha.Url == "" || global.GVA_CONFIG.Recaptcha.Key == "" {
		response.FailWithMessage("config key empty",ctx)
		return
	}
	err := address.CheckAddress(recaptcha.Addr,-1)
	if err != nil {
		response.FailWithMessage("地址错误",ctx)
		return
	}
	//如果是eth地址 转化为小写
	if address.IsEthAddress(recaptcha.Addr) {
		recaptcha.Addr = strings.ToLower(recaptcha.Addr)
	}
	resp, err := http.PostForm(global.GVA_CONFIG.Recaptcha.Url, url.Values{"secret": {global.GVA_CONFIG.Recaptcha.Key}, "response": {recaptcha.Response}})
	if err != nil {
		global.GVA_LOG.Error("Recaptcha post err",zap.Error(err))
		response.FailWithMessage(err.Error(), ctx)
		return
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)

	if err != nil {
		global.GVA_LOG.Error("Recaptcha read data err",zap.Error(err))
		response.FailWithMessage(err.Error(), ctx)
		return
	}

	var responseData application.RecaptchaResponse
	if err := json.Unmarshal(body, &responseData); err != nil {
		global.GVA_LOG.Error("Recaptcha unmarshal err",zap.Error(err))
		response.FailWithMessage(err.Error(), ctx)
		return
	}

	if !responseData.Success {
		response.FailWithMessage("unsuccessful recaptcha verify request", ctx)
		return
	}
	global.GVA_LOG.Debug("verifiy",zap.Float64p(" socre ",&responseData.Score))
	//if responseData.Score < 0.5 {
	//	response.FailWithMessage("ulower received score than expected", ctx)
	//	return
	//}

	//validateEmail := app_service.ValidateEmailReq{
	//	CodeType: "snatch_red_envelope",
	//	Email:    recaptcha.Email,
	//}
	//err = validateEmail.SendEmail()
	//if err != nil {
	//	response.FailWithMessage(err.Error(), ctx)
	//	return
	//}
	tx := global.GVA_DB.Begin()
	var rp airDrop.RedPackage
	err = tx.Table("red_package").Where("id = ?",recaptcha.Pid).Find(&rp).Error
	if err != nil {
		tx.Rollback()
		global.GVA_LOG.Error(err.Error())
		response.FailWithMessage("数据库错误",ctx)
		return
	}
	if !rp.IsShow {
		tx.Rollback()
		response.FailWithMessage("红包不能领取",ctx)
		return
	}
	if rp.RemainNum == 0 || rp.Remain == 0  {
		tx.Rollback()
		response.FailWithMessage("红包已抢完",ctx)
		return
	}
	if rp.White != "" && !strings.Contains(rp.White,recaptcha.Addr) {
		tx.Rollback()
		response.FailWithMessage("address not allowed",ctx)
		return
	}
	if rp.IsBlack {
		exists := &user.Users{}
		err = tx.Table("users").Where("address = ?",recaptcha.Addr).First(exists).Error
		if err != nil && err != gorm.ErrRecordNotFound {
			tx.Rollback()
			response.FailWithMessage("data sql err"+err.Error(),ctx)
			return
		}
		if err == nil && *exists.IsBlack {
			tx.Rollback()
			response.FailWithMessage("address limited",ctx)
			return
		}
	}
	if rp.IsPassword {
		if recaptcha.Pwd == "" {
			tx.Rollback()
			response.FailWithMessage("password not set",ctx)
			return
		}
		if rp.Password != utils.Sha256String(recaptcha.Pwd) {
			global.GVA_LOG.Error("pwd",zap.String("right",rp.Password),zap.String("req sha256",utils.Sha256String(recaptcha.Pwd)),zap.String("req pwd",recaptcha.Pwd))
			tx.Rollback()
			response.FailWithMessage("password not right",ctx)
			return
		}
	}
	var count,count2 int64
	err = tx.Table("red_package_tx").Where("pid = ? and addr = ?",recaptcha.Pid,recaptcha.Addr).Count(&count).Error
	if err != nil {
		tx.Rollback()
		global.GVA_LOG.Error(err.Error())
		response.FailWithMessage("数据库错误",ctx)
		return
	}
	if count >= 1 {
		var record airDrop.RedPackageTx
		err = tx.Table("red_package_tx").Where("pid = ? and addr = ?",recaptcha.Pid,recaptcha.Addr).First(&record).Error
		if err != nil {
			tx.Rollback()
			response.FailWithMessage("数据库错误",ctx)
			return
		}
		tx.Commit()
		response.OkWithData(gin.H{"tx":record},ctx)
		return
	}
	//已有记录 先显示 再判断redpackage 是否过期
	if rp.EndAt.Unix() < time.Now().Unix() {
		tx.Rollback()
		response.FailWithMessage("红包已过期",ctx)
		return
	}
	ip := ctx.ClientIP()
	err = tx.Table("red_package_tx").Where("pid = ? and ip = ?",recaptcha.Pid,ip).Count(&count2).Error
	if err != nil {
		tx.Rollback()
		global.GVA_LOG.Error(err.Error())
		response.FailWithMessage("数据库错误",ctx)
		return
	}
	if int(count2) > rp.IpLimit {
		tx.Rollback()
		response.FailWithMessage("IP限制3次",ctx)
		return
	}
	//有白名单 地址须在白名单之内

	amount := rp.GetRandOne()
	if amount == 0 {
		tx.Rollback()
		response.FailWithMessage("红包余额已抢完",ctx)
		return
	}
	err = tx.Table("red_package").Where("id = ?",recaptcha.Pid).UpdateColumns(map[string]interface{}{"remain":gorm.Expr("remain - ?",amount),"remain_num":gorm.Expr("remain_num - ?",1)}).Error
	if err != nil {
		tx.Rollback()
		global.GVA_LOG.Error(err.Error())
		response.FailWithMessage("数据库异常",ctx)
		return
	}
	trans := &airDrop.RedPackageTx{
		Amount:    amount,
		Addr:      recaptcha.Addr,
		Pid:       int(recaptcha.Pid),
		Ip:			ip,
	}
	err = tx.Table("red_package_tx").Save(trans).Error
	if err != nil {
		tx.Rollback()
		global.GVA_LOG.Error(err.Error())
		response.FailWithMessage("奖励生成失败",ctx)
		return
	}
	tx.Commit()
	response.OkWithData(gin.H{"tx":trans}, ctx)
}

// RecaptchaVps 声纹验证 通过直接分配红包 0、创建分组（脚本任务在福袋创建后触发）1、地址是否已领取 2、声纹识别1：N查询 score<0.6 非法语音 score>=0.6 声纹已领取
// @Tags RecaptchaVps
// @Summary 验证码 通过直接领取红包
// @accept application/json
// @Produce application/json
// @Param data body application.RecaptchaAndDrawRequest true "验证码 通过直接领取红包"
// @Success 200
// @Router /verification/recaptchaVps [post]
func (s *VerificationApi) RecaptchaVps(ctx *gin.Context) {
	var recaptcha application.RecaptchaAndDrawRequest
	_ = ctx.ShouldBindJSON(&recaptcha)
	if err := utils.Verify(recaptcha, utils.VoiceVerify); err != nil {
		global.GVA_LOG.Error("RecaptchaVps verify err",zap.Error(err))
		response.FailWithMessage(err.Error(), ctx)
		return
	}
	err := address.CheckAddress(recaptcha.Addr,-1)
	if err != nil {
		response.FailWithMessage("地址错误",ctx)
		return
	}
	if recaptcha.Ty == 1 {
		err = redPackageService.ResetVerify(recaptcha.Addr,recaptcha.Pid)
		if err != nil {
			global.GVA_LOG.Error("ResetVerify failed", zap.Error(err))
			response.FailWithMessage(err.Error(), ctx)
		} else {
			response.OkWithMessage("ok",ctx)
		}
		return
	}
	if _,isOk := global.BlackCache.Get(recaptcha.Addr);isOk{
		response.FailWithMessage("请求频率过快",ctx)
		return
	} else {
		global.BlackCache.Set(recaptcha.Addr,1,time.Second * 30)
	}
	// 如果是eth地址 转化为小写
	// if address.IsEthAddress(recaptcha.Addr) {
	// 	recaptcha.Addr = strings.ToLower(recaptcha.Addr)
	// }
	ip := ctx.ClientIP()
	trans,err := redPackageService.CheckUserPackage(ip,recaptcha.Addr,recaptcha.Pid,recaptcha.Pwd)
	if err != nil && err != errno.ErrVoiceVerifyNotPass {
		global.GVA_LOG.Error("地址和红包验证失败", zap.Error(err))
		response.FailWithMessage(err.Error(), ctx)
		return
	} else if err != nil && err == errno.ErrVoiceVerifyNotPass {
		global.GVA_LOG.Error("地址和红包验证失败", zap.Error(err))
		response.Result(errno.ErrVoiceVerifyNotPass.Code,nil,errno.ErrVoiceVerifyNotPass.Error(),ctx)
		return
	}
	if trans != nil && trans.ID > 0 {
		response.OkWithData(gin.H{"tx":trans}, ctx)
		return
	}
	if tx,err := redPackageService.AddNewUserPackage(ip,recaptcha.Addr,recaptcha.Pid,""); err != nil {
		global.GVA_LOG.Error("分发红包错误", zap.Error(err))
		response.FailWithMessage("分发红包错误", ctx)
		return
	} else {
		response.OkWithData(gin.H{"tx":tx}, ctx)
	}
	return
	// var recaptcha application.RecaptchaAndDrawRequest
	// _ = ctx.ShouldBind(&recaptcha)
	// if err := utils.Verify(recaptcha, utils.VoiceVerify); err != nil {
	// 	global.GVA_LOG.Error("RecaptchaVps verify err",zap.Error(err))
	// 	response.FailWithMessage(err.Error(), ctx)
	// 	return
	// }
	// noSave := ctx.DefaultQuery("noSave", "0")
	// global.GVA_LOG.Debug("RecaptchaVps",zap.Any("addr",recaptcha.Addr),zap.Any("pid",recaptcha.Pid))
	// addr := ctx.PostForm("addr")
	// pid,_:= strconv.Atoi(ctx.PostForm("pid"))
	// global.GVA_LOG.Debug("RecaptchaVps2",zap.Any("addr",addr),zap.Any("pid",pid))
	// if global.GVA_CONFIG.VoiceServer.ApiSecret == "" || global.GVA_CONFIG.VoiceServer.ApiKey == "" || global.GVA_CONFIG.VoiceServer.AppId == "" {
	// 	response.FailWithMessage("voice config key empty",ctx)
	// 	return
	// }
	// err := address.CheckAddress(recaptcha.Addr,-1)
	// if err != nil {
	// 	response.FailWithMessage("地址错误",ctx)
	// 	return
	// }
	// if _,isOk := global.BlackCache.Get(recaptcha.Addr);isOk{
	// 	response.FailWithMessage("请求频率过快",ctx)
	// 	return
	// } else {
	// 	global.BlackCache.Set(recaptcha.Addr,1,time.Minute)
	// }
	// // 如果是eth地址 转化为小写
	// if address.IsEthAddress(recaptcha.Addr) {
	// 	recaptcha.Addr = strings.ToLower(recaptcha.Addr)
	// }
	// ip := ctx.ClientIP()
	// // 先检测地址和红包信息
	// trans,err := redPackageService.CheckUserPackage(ip,recaptcha.Addr,recaptcha.Pid);
	// if err != nil {
	// 	global.GVA_LOG.Error("地址和红包验证失败", zap.Error(err))
	// 	response.FailWithMessage(err.Error(), ctx)
	// 	return
	// }
	// if trans != nil && trans.ID > 0 {
	// 	response.OkWithData(gin.H{"tx":trans}, ctx)
	// 	return
	// }
	// _,header,err := ctx.Request.FormFile("audioFile")
	// if err != nil {
	// 	global.GVA_LOG.Error("接受文件失败", zap.Error(err))
	// 	response.FailWithMessage(err.Error(), ctx)
	// 	return
	// }
	// file, err := fileUploadAndDownloadService.UploadFile(header, noSave) // 文件上传后拿到文件路径
	// if err != nil {
	// 	global.GVA_LOG.Error("文件上传失败!", zap.Error(err))
	// 	response.FailWithMessage("文件上传失败", ctx)
	// 	return
	// }
	// global.GVA_LOG.Info("save file ",zap.String("url",file.Url))
	// defer ctx.Request.Body.Close()
	// vBytes,err := io.ReadAll(ctx.Request.Body)
	// if err != nil {
	// 	global.GVA_LOG.Error("读取文件失败!", zap.Error(err))
	// 	response.FailWithMessage("读取文件失败", ctx)
	// 	return
	// }
	// wav to mp3
	// f,err := os.Open(file.Url)
	// if err != nil {
	// 	global.GVA_LOG.Error("open file failed!", zap.Error(err))
	// 	response.FailWithMessage("open file failed", ctx)
	// 	return
	// }
	// defer f.Close()
	// vBytes,err := ioutil.ReadAll(f)
	// if err != nil {
	// 	global.GVA_LOG.Error("read file failed!", zap.Error(err))
	// 	response.FailWithMessage("read file failed", ctx)
	// 	return
	// }
	// global.GVA_LOG.Info("vBytes buf",zap.Any("size",len(vBytes)))
	// buf, err := ai.Wav2mp3(vBytes)
	// if err != nil {
	// 	global.GVA_LOG.Error("格式转化失败!", zap.Error(err))
	// 	response.FailWithMessage("格式转化失败", ctx)
	// 	return
	// }
	// // mp3 data to base64 encode
	// audio := base64.StdEncoding.EncodeToString(buf)
	// global.GVA_LOG.Info("audio buf",zap.Any("size",len(audio)))
	// fs := strings.Split(file.Url,".")
	// mp3,err := os.Create(fs[0]+".mp3")
	// if err != nil {
	// 	global.GVA_LOG.Error("mp3保存失败!", zap.Error(err))
	// 	response.FailWithMessage("mp3保存失败", ctx)
	// 	return
	// }
	// defer mp3.Close()
	// _,err = mp3.Write(buf)
	// if err != nil {
	// 	if err != nil {
	// 		global.GVA_LOG.Error("mp3写入失败!", zap.Error(err))
	// 		response.FailWithMessage("mp3写入失败", ctx)
	// 		return
	// 	}
	// }
	// gid := ai.GetGroupId(recaptcha.Pid)
	// featureId := recaptcha.Addr
	// if len(featureId) > 32 {
	// 	featureId = recaptcha.Addr[:32]
	// }
	// featureInfo := featureId
	// // first, use searchScoreFea(1:1) to find featureId
	// ri := &ai.ReqVpsInfo{
	// 	AppId: global.GVA_CONFIG.VoiceServer.AppId,
	// 	ApiSecret: global.GVA_CONFIG.VoiceServer.ApiSecret,
	// 	ApiKey: global.GVA_CONFIG.VoiceServer.ApiKey,
	// 	GroupId:   gid,
	// 	ApiName:   "searchScoreFea",
	// 	FeatureId: featureId,
	// 	Audio:     audio,
	// }
	//
	// // 不存在声纹 先录入声纹  绑定地址  再分发红包
	// ri.ApiName = "createFeature"
	// ri.FeatureId = featureId
	// ri.FeatureInfo = featureInfo
	// res, code, err := ai.Vrg(ri)
	// global.GVA_LOG.Debug("createFeature",zap.Any("res",res),zap.Any("code",code),zap.Any("err",err))
	// if err != nil {
	// 	global.GVA_LOG.Error("createFeature err",zap.Any(featureId,err))
	// 	response.FailWithMessage("createFeature failed", ctx)
	// 	return
	// }
	// err = redPackageService.BindFeature(recaptcha.Addr,res.FeatureId)
	// if err != nil {
	// 	global.GVA_LOG.Error("BindFeature err",zap.Any(featureId,err))
	// 	response.FailWithMessage("BindFeature failed", ctx)
	// 	return
	// }
	//
	// ri.ApiName = "searchScoreFea"
	// res, code, err = ai.Vrg(ri)
	// global.GVA_LOG.Debug("searchScoreFea",zap.Any("res",res),zap.Any("code",code),zap.Any("err",err))
	// if err != nil {
	// 	println("Failed to search srore feature", err.Error())
	// 	//if code != 23007 {
	// 		global.GVA_LOG.Error("请求接口1:1失败!", zap.Error(err))
	// 		response.FailWithMessage("请求接口1:1失败", ctx)
	// 		return
	// 	//}
	// }
	// // if featureId exists, checkin
	// if res != nil && res.FeatureId == featureId {
	// 	if res.Score > 0.6 { //  我是我
	// 		// 判断 是否已领取
	// 		if tx,err := redPackageService.AddNewUserPackage(ip,recaptcha.Addr,recaptcha.Pid,res.FeatureId); err != nil {
	// 			global.GVA_LOG.Error("分发红包错误", zap.Error(err))
	// 			response.FailWithMessage(err.Error(), ctx)
	// 		} else {
	// 			response.OkWithData(gin.H{"tx":tx}, ctx)
	// 		}
	// 	} else {
	// 		global.GVA_LOG.Error("声纹验证不通过", zap.Error(err))
	// 		response.FailWithMessage("声纹验证不通过,请重新录音", ctx)
	// 	}
	// 	return
	// }
	// second, use searchFea(1:N) to find featureId
	// ri.ApiName = "searchFea"
	// res, code, err = ai.Vrg(ri)
	// global.GVA_LOG.Debug("searchFea",zap.Any("res",res),zap.Any("code",code),zap.Any("err",err))
	// if err != nil {
	// 	println("Failed to search feature", err.Error())
	// 	if code != 23008 {
	// 		global.GVA_LOG.Error("声纹识别1:N失败", zap.Error(err))
	// 		response.FailWithMessage("声纹识别1:N失败", ctx)
	// 		return
	// 	}
	// }
	// // 已存在声纹
	// if res != nil && res.Score >= 0.6{
	// 	global.GVA_LOG.Error("声纹已领取", zap.Error(err))
	// 	response.FailWithMessage("声纹已领取", ctx)
	// 	return
	// } else if res != nil && res.Score < 0.6 {
	// 	global.GVA_LOG.Error("声纹识别失败", zap.Error(err))
	// 	response.FailWithMessage("请尝试正常录音", ctx)
	// 	return
	// }


	// if tx,err := redPackageService.AddNewUserPackage(ip,recaptcha.Addr,recaptcha.Pid,res.FeatureId); err != nil {
	// 	global.GVA_LOG.Error("分发红包错误", zap.Error(err))
	// 	response.FailWithMessage("分发红包错误", ctx)
	// 	return
	// } else {
	//
	// 	response.OkWithData(gin.H{"tx":tx}, ctx)
	// }

}

// RecaptchaTele 验证 通过直接分配红包
// @Tags Recaptcha
// @Summary 验证码 通过直接领取红包
// @accept application/json
// @Produce application/json
// @Param data body application.RecaptchaAndDrawRequest true "通过直接领取红包"
// @Success 200
// @Router /verification/tele [post]
func (s *VerificationApi) RecaptchaTele(ctx *gin.Context) {
	var recaptcha application.RecaptchaAndDrawRequest
	_ = ctx.ShouldBindJSON(&recaptcha)
	if err := utils.Verify(recaptcha, utils.AddressVerify); err != nil {
		global.GVA_LOG.Error("Recaptcha verify err", zap.Error(err))
		response.FailWithMessage(err.Error(), ctx)
		return
	}
	err := address.CheckAddress(recaptcha.Addr,-1)
	if err != nil {
		response.FailWithMessage("地址错误",ctx)
		return
	}

	if _,isOk := global.BlackCache.Get(recaptcha.Addr);isOk{
		response.FailWithMessage("请求频率过快",ctx)
		return
	} else {
		global.BlackCache.Set(recaptcha.Addr,1,time.Second * 10)
	}
	//如果是eth地址 转化为小写
	if address.IsEthAddress(recaptcha.Addr) {
		recaptcha.Addr = strings.ToLower(recaptcha.Addr)
	}

	ip := ctx.ClientIP()
	trans,err := redPackageService.CheckUserPackageTele(ip,recaptcha.Addr,recaptcha.Pid,recaptcha.Pwd)
	if err != nil {
		global.GVA_LOG.Error("地址和红包验证失败", zap.Error(err))
		response.FailWithMessage(err.Error(), ctx)
		return
	}
	if trans != nil && trans.ID > 0 {
		response.OkWithData(gin.H{"tx":trans}, ctx)
		return
	}
	if tx,err := redPackageService.AddNewUserPackage(ip,recaptcha.Addr,recaptcha.Pid,""); err != nil {
		global.GVA_LOG.Error("分发红包错误", zap.Error(err))
		response.FailWithMessage("分发红包错误", ctx)
		return
	} else {
		response.OkWithData(gin.H{"tx":tx}, ctx)
	}
	return
}