package router

import (
	"demo/configs"
	"demo/data/dao"
	"demo/data/dao/manage"
	"demo/data/domain"
	"demo/data/domain/vo"
	"demo/share"
	"demo/util"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/mojocn/base64Captcha"
	"github.com/spf13/cast"
	"log"
	"math/big"
	"net/http"
	"regexp"
	"strconv"
	"strings"
	"time"
)

func UserRouth(engine *gin.RouterGroup) {
	user := engine.Group("/user")
	//{
	//	//获取用户基本信息
	//	user.GET("/info", GetUserInfo)
	//	//获取用户钱包
	//	user.GET("/wallet", GetUserWallet)
	//	//修改名字
	//	user.PUT("/name", SetNameValue)
	//	//获取用户的订单信息
	//	user.POST("/order", GetUserOrder)
	//	//用户登录
	//	user.POST("/login", login)
	//	//注册
	//	user.POST("/register", register)
	//
	//	//发送邮箱注册验证码
	//	user.POST("/registerCode", registerCode)
	//	//发送验证码
	//	user.POST("/sendSms", SendVerificationCode)
	//	//图片验证码
	//	user.GET("/captcha", VerificationCode)
	//}
	//获取用户基本信息

	PushRouter(user, "GET", "/info", GetUserInfo)
	//获取用户钱包
	PushRouter(user, "GET", "/wallet", GetUserWallet)
	//修改名字
	PushRouter(user, "PUT", "/name", SetNameValue)
	//获取用户的订单信息
	PushRouter(user, "POST", "/order", GetUserOrder)
	//用户登录
	PushRouter(user, "POST", "/login", login)
	//注册
	PushRouter(user, "POST", "/register", register)
	//发送邮箱注册验证码
	PushRouter(user, "POST", "/registerCode", registerCode)
	//发送验证码
	PushRouter(user, "POST", "/sendSms", SendVerificationCode)
	//图片验证码
	PushRouter(user, "GET", "/captcha", VerificationCode)
	PushRouter(user, "GET", "/base/info", GetUserBaseInfo)
	PushRouter(user, "POST", "/base/info", GetUserBaseInfoList)
}

func GetUserBaseInfo(c *gin.Context) {
	id := c.Query("userId")
	if id == "" {
		c.JSON(200, CreateResultError(401, "参数不全"))
		return
	}
	user, err := manage.GetUserById(cast.ToInt64(id))
	if err != nil {
		c.JSON(200, CreateResultError(401, "用户不存在"))
		return
	}
	m := make(map[string]interface{})
	m["id"] = user.Id
	m["name"] = user.Name
	m["avatar"] = user.Avatar
	c.JSON(200, CreateResultData(m))
}
func GetUserBaseInfoList(c *gin.Context) {
	data := share.GetJsonAnyParam(c)
	idsData, _ := data("ids")
	split := strings.Split(cast.ToString(idsData), ",")
	var ids = make([]int64, 0)
	for i := range split {
		parseInt, _ := strconv.ParseInt(split[i], 10, 64)
		ids = append(ids, parseInt)
	}

	users, err := manage.GetUserListInId(ids)
	if err != nil {
		c.JSON(200, CreateResultError(401, "用户不存在"))
		return
	}
	vos := make([]vo.UserBaseInfoVo, 0)

	for i := range users {
		user := vo.UserBaseInfoVo{
			Id:     users[i].Id,
			Name:   users[i].Name,
			Avatar: users[i].Avatar,
		}
		vos = append(vos, user)
	}

	c.JSON(200, CreateResultData(vos))
}

// GetUserInfo 获取用户的个人信息
func GetUserInfo(c *gin.Context) {
	header := c.GetHeader("auth-sign")
	if header == "" {
		c.JSON(200, CreateResultError(401, "用户未登录"))
		return
	}
	claims, err := share.ParseToken(header)
	if err != nil {
		c.JSON(200, CreateResultError(401, "用户未登录"))
		return
	}
	var userInfo = domain.User{}
	_, err = configs.Engine.Table("user").Where("id = ?", claims["iss"]).Get(&userInfo)
	if err != nil {
		c.JSON(200, CreateResultError(401, "用户未登录"))
		return
	}
	c.JSON(200, CreateResultData(userInfo))
}

func GetUserWallet(c *gin.Context) {
	id := GetUserIdByToken(c)
	if id == 0 {
		return
	}
	var vo vo.UserWalletVo
	userWallet, err := dao.GetUserWalletByUserId(id)
	if err != nil {
		c.JSON(200, CreateResultError(500, "获取钱包失败"))
		return
	}
	vo.Wallet = userWallet
	vo.CouponUserJDM, err = dao.GetUserCouponByUserId(id)
	if err != nil {
		c.JSON(200, CreateResultError(500, "获取优惠券失败"))
		return
	}
	c.JSON(200, CreateResultData(vo))
}
func SetNameValue(c *gin.Context) {
	id := GetUserIdByToken(c)
	if id == 0 {
		return
	}
	name := c.Query("name")
	fmt.Println(name)
	_, b, err := manage.SetUser(map[string]interface{}{"name": name}, id)
	if err != nil {
		println(err.Error())
		c.JSON(200, CreateResultError(500, "修改失败"))
		return
	}
	if b {
		c.JSON(200, CreateResult())
	} else {
		c.JSON(200, CreateResultError(500, "修改失败"))
	}
}

// GetUserOrder 获取用户订单信息
func GetUserOrder(c *gin.Context) {
	id := GetUserIdByToken(c)
	if id == 0 {
		return
	}
	data := share.GetJsonAnyParam(c)
	pageNum, _ := data("pageNum")
	pageSize, _ := data("pageSize")
	state, _ := data("state")
	vo, err := dao.GetListGoodsOrder(cast.ToString(state), id, cast.ToInt(pageNum), cast.ToInt(pageSize))
	if err != nil {
		c.JSON(200, CreateResultError(500, "获取订单失败"))
		return
	}
	c.JSON(200, CreateResultData(vo))
}

func VerificationCode(c *gin.Context) {
	// 配置
	driver := base64Captcha.NewDriverDigit(80, 240, 4, 0.5, 80)
	store := base64Captcha.DefaultMemStore
	captcha := base64Captcha.NewCaptcha(driver, store)

	// 生成验证码
	id, b64s, answer, err := captcha.Generate()
	if err != nil {
		c.JSON(500, gin.H{"error": err.Error()})
		return
	}

	err = configs.RedisDb.Set(ctx, "VerificationCode_"+id, answer, 0).Err()
	if err != nil {
		fmt.Println(err)
	}
	err = configs.RedisDb.Expire(ctx, "VerificationCode_"+id, 60*time.Second).Err()
	if err != nil {
		panic(err)
	}
	// 返回验证码图片
	c.JSON(200, gin.H{
		"message": "获取成功!!!",
		"expires": time.Now().Add(time.Minute * 5).Unix(),
		"code":    200,
		"data":    map[string]string{"id": id, "image": b64s},
	})
}

func login(c *gin.Context) {
	data := share.GetJsonAnyParam(c)
	var user domain.User
	var err error
	username, _ := data("username")
	password, _ := data("password")
	t, _ := data("type")
	// 定义正则表达式

	if cast.ToString(t) == "email" {
		regexPattern := `^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`
		// 编译正则表达式
		reg, err := regexp.Compile(regexPattern)
		if err != nil {
			fmt.Println("编译正则表达式时出错:", err)
			return
		}
		//判断是否为邮箱格式
		matched := reg.MatchString(cast.ToString(username))

		if !matched {
			fmt.Println("无效的电子邮件格式.")
			c.JSON(http.StatusOK, CreateResultError(400, "邮箱格式错误!!!"))
			return
		}
	} else if cast.ToString(t) == "phone" {
		regexPattern := `^1[3-9]\d{9}$`
		// 编译正则表达式
		reg, err := regexp.Compile(regexPattern)
		if err != nil {
			fmt.Println("编译正则表达式时出错:", err)
			return
		}
		//判断是否为邮箱格式
		matched := reg.MatchString(cast.ToString(username))

		if !matched {
			fmt.Println("无效的手机号格式.")
			c.JSON(http.StatusOK, CreateResultError(400, "手机格式错误!!!"))
			return
		}
	}

	user, err = dao.Logins(cast.ToString(username), cast.ToString(password), cast.ToString(t))

	if err == nil && user.Id != 0 {
		fmt.Println("用户登录成功!!!")
		token, err := share.GenerateToken(cast.ToString(user.Id))
		if err == nil {
			c.Header("auth-sign", token)
			c.JSON(http.StatusOK, CreateResultData(map[string]string{"token": token}))
		} else {
			c.JSON(http.StatusOK, CreateResultError(400, "生成token失败!!!"))
		}
	} else {
		fmt.Println("用户登录失败!!!")
		c.JSON(http.StatusOK, CreateResultError(401, "用户密码错误!!!"))
	}
}

func registerCode(c *gin.Context) {
	data := share.GetJsonAnyParam(c)
	phone, _ := data("phone")
	//判断是否为手机格式
	if !checkPhone(c, cast.ToString(phone)) {
		return
	}
	//判断是否已经注册
	b, err := dao.ExistsPhone(cast.ToString(phone))
	if err != nil {
		fmt.Println(err)
		c.JSON(http.StatusOK, CreateResultError(200, "数据库错误!!!"))
		return
	}
	if b {
		c.JSON(http.StatusOK, CreateResultError(200, "手机号已注册!!!"))
		return
	}
	//判断是否重复注册
	get := configs.RedisDb.Exists(ctx, "PhoneVerificationCodeTime_"+cast.ToString(phone))
	if get.Val() == 1 {
		c.JSON(http.StatusOK, CreateResultError(200, "验证码已经发送，请等待"))
		return
	}

	//发送短信
	//sms := sendSms(b, cast.ToString(phone))
	//TODO 模拟发送短信
	sms := testSendSms()
	fmt.Println("发送成功!!!:验证码为:", sms)
	configs.RedisDb.Set(ctx, "PhoneVerificationCode_"+cast.ToString(phone), sms, 60*5*time.Second)
	configs.RedisDb.Set(ctx, "PhoneVerificationCodeTime_"+cast.ToString(phone), time.Now(), 60*time.Second)
	c.JSON(http.StatusOK, CreateResult())

}

func testSendSms() string {
	mins := big.NewInt(100000)
	maxs := big.NewInt(999999)
	randomNum := share.RandomInt(mins, maxs)
	//if matched {
	//	//bools, err = configs.Engine.Table("user").Where("username = ?", username).Exist(&user)
	//
	//	share.SendMail(username, strconv.Itoa(int(randomNum.Int64())))
	//
	//} else {
	//	share.SendSms(strconv.Itoa(int(randomNum.Int64())), username)
	//}
	return randomNum.String()
}

func register(c *gin.Context) {

	data := share.GetJsonAnyParam(c)

	username, _ := data("username")
	password, _ := data("password")
	code, _ := data("code")
	phone, _ := data("phone")

	if !checkEmail(c, cast.ToString(username)) {
		return
	}
	if !checkPhone(c, cast.ToString(phone)) {
		return
	}
	if !checkCode(c, cast.ToString(code)) {
		return
	}
	if !checkPassword(c, cast.ToString(password)) {
		return
	}
	// 验证验证码
	get := configs.RedisDb.Get(ctx, "PhoneVerificationCode_"+cast.ToString(phone))
	fmt.Println(code, get.Val())
	if code != get.Val() {
		c.JSON(http.StatusOK, CreateResultError(400, "验证码错误!"))
		return
	}
	configs.RedisDb.Del(ctx, "PhoneVerificationCode_"+cast.ToString(phone))

	//判断是否已经注册
	b, err := dao.GetUserByPhoneOrEmail(cast.ToString(phone), cast.ToString(username))
	if err != nil {
		c.JSON(http.StatusOK, CreateResultError(400, "验证手机号及用户名，数据错误"))
		return
	}
	if b {
		c.JSON(http.StatusOK, CreateResultError(400, "手机号或邮箱已注册!!!"))
		return
	}

	timestamp := time.Now().Unix()
	user := domain.User{
		Username:      cast.ToString(username),
		Password:      cast.ToString(password),
		CreationTime:  timestamp,
		Status:        "0",
		RoleId:        2,
		Phone:         cast.ToString(phone),
		Email:         cast.ToString(username),
		Name:          cast.ToString(username),
		RecommendCode: fmt.Sprint(strconv.FormatInt(timestamp, 16), util.RandomArrays(13, 62)),
	}

	user, err = dao.SaveNewUser(user)
	if err != nil {
		fmt.Println(err)
		c.JSON(http.StatusOK, CreateResultError(400, "数据库错误!!!"))
		return
	}
	if user.Id != 0 {
		fmt.Println("用户注册成功!!!")
		c.JSON(http.StatusOK, CreateResultData(map[string]any{"user": user}))
		//用户钱包添加
		manage.SaveUserWallet(&domain.UserWallet{UserId: user.Id})

		return
	} else {
		fmt.Println("用户注册失败!!!")
		c.JSON(http.StatusOK, CreateResultError(400, "用户注册失败!!!"))
		return
	}
}

func checkEmail(c *gin.Context, email string) bool {
	//// 定义正则表达式
	regexPattern := `^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`
	reg, err := regexp.Compile(regexPattern)
	if err != nil {
		fmt.Println("Error compiling regex:", err)
		c.JSON(500, CreateResultError(500, "邮箱格式错误!!!"))
		return false
	}
	//判断是否为邮箱格式
	matched := reg.MatchString(cast.ToString(email))
	if !matched {
		fmt.Println("Error compiling regex:", err)
		c.JSON(500, CreateResultError(500, "邮箱格式错误!!!"))
		return false
	}
	return true
}
func checkPhone(c *gin.Context, phone string) bool {
	//// 定义正则表达式
	regexPattern := `^1[3-9]\d{9}$`
	reg, err := regexp.Compile(regexPattern)
	if err != nil {
		fmt.Println("1 Error compiling regex:", err)
		c.JSON(200, CreateResultError(500, "手机号格式错误!!!"))
		return false
	}
	matched := reg.MatchString(cast.ToString(phone))
	if !matched {
		fmt.Println("2 Error compiling regex:", err)
		c.JSON(200, CreateResultError(500, "手机号格式错误!!!"))
		return false
	}
	return true
}
func checkPassword(c *gin.Context, email string) bool {
	//// 定义正则表达式
	regexPattern := `^[a-zA-Z0-9,./<>?;'\\:"|\[\]{}~!@#$%^&*()_+=-]{6,32}$`
	reg, err := regexp.Compile(regexPattern)
	if err != nil {
		fmt.Println("Error compiling regex:", err)
		c.JSON(500, CreateResultError(500, "密码格式错误!!!"))
		return false
	}
	//判断是否为邮箱格式
	matched := reg.MatchString(cast.ToString(email))
	if !matched {
		fmt.Println("Error compiling regex:", err)
		c.JSON(500, CreateResultError(500, "密码格式错误!!!"))
		return false
	}
	return true
}
func checkCode(c *gin.Context, code string) bool {
	//// 定义正则表达式
	regexPattern := `^\d{6}$`
	reg, err := regexp.Compile(regexPattern)
	if err != nil {
		fmt.Println("Error compiling regex:", err)
		c.JSON(500, CreateResultError(500, "验证码格式错误!!!"))
		return false
	}
	//判断是否为邮箱格式
	matched := reg.MatchString(cast.ToString(code))
	if !matched {
		fmt.Println("Error compiling regex:", err)
		c.JSON(500, CreateResultError(500, "验证码格式错误!!!"))
		return false
	}

	return true
}

// SendVerificationCode 发送验证码
func SendVerificationCode(c *gin.Context) {
	data := share.GetJsonAnyParam(c)
	var err error
	username, _ := data("username")
	code, _ := data("code")
	codeId, _ := data("codeId")
	val, err := configs.RedisDb.Get(ctx, cast.ToString(codeId)).Result()
	if err != nil {
		log.Fatal(err)
	}
	if val != cast.ToString(code) {
		c.JSON(200, gin.H{"code": 400, "message": "验证码错误!!!"})
		c.Abort()
		return
	}
	// 定义正则表达式
	regexPattern := `^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`

	// 编译正则表达式
	reg, err := regexp.Compile(regexPattern)
	if err != nil {
		fmt.Println("Error compiling regex:", err)
		return
	}
	matched := reg.MatchString(cast.ToString(username))
	dao.SendSms(matched, cast.ToString(username))
	c.JSON(200, gin.H{"code": 200, "message": "发送成功!!!"})
}
