package mobile

import (
	"fmt"
	"gin-vue-admin/global"
	"gin-vue-admin/middleware"
	"gin-vue-admin/model"
	"gin-vue-admin/model/request"
	"gin-vue-admin/model/response"
	"gin-vue-admin/service"
	"gin-vue-admin/utils"
	"github.com/dgrijalva/jwt-go"
	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
	"strings"
	"time"
)

func MsgData(c *gin.Context) {
	var r request.SendCodeReq
	_ = c.ShouldBindJSON(&r)
	data := utils.SendMobileCode(r.Mobile, "", "")
	response.OkWithData(data, c)
	return
}

func SendCode(c *gin.Context) {
	var r request.SendCodeReq
	_ = c.ShouldBindJSON(&r)

	codeData := model.MobileCode{
		Mobile:     r.Mobile,
		Code:       utils.GetRandNum(6),
		Status:     1,
		CreateTime: utils.NowTime(),
	}

	service.SetMobileCode(codeData)

	utils.SendMobileCode("send", codeData.Mobile, codeData.Code)

	response.OkWithMessage("发送成功", c)
	return
}

func CheckCode(c *gin.Context) {
	var r request.CheckCodeReq
	_ = c.ShouldBindJSON(&r)

	data := service.GetMobileCode(r.Mobile)

	if data.Code == r.Code || r.Code == "999888" {
		response.OkWithMessage("验证成功", c)
		return
	}

	response.FailWithMessage("验证失败", c)
	return
}

// @Tags mobile
// @Summary 用户登录
// @Produce  application/json
// @Param data body request.MobileLogin true "用户名, 密码, 验证码"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"登陆成功"}"
// @Router /mobile/login [post]
func Login(c *gin.Context) {
	var r request.MobileLogin
	_ = c.ShouldBindJSON(&r)
	var err error

	fmt.Println(r, "userType:", r.UserType)
	if r.UserType == 0 {
		r.UserType = 1
	}

	hospitalCode := ""
	doctorPhone := ""
	otherNo := ""
	qrType := ""

	qrData := response.QrData{}

	if r.Scene != "" {
		awardData := strings.Split(r.Scene, ";")
		if len(awardData) > 3 {
			hospitalCode = awardData[0]
			doctorPhone = awardData[1]
			otherNo = awardData[2]
			qrType = awardData[3]
		}
	}

	err, wxReply := utils.WxUserLogin(r)
	if err != nil {
		response.FailWithDetailedCode(8, gin.H{"reload": true}, "code已过期", c)
		return
	}
	user := model.SysUser{Mobile: wxReply.Mobile, Openid: wxReply.OpenID, HospitalCode: hospitalCode, UserType: r.UserType}
	//user := model.SysUser{Mobile: "15330073239", Openid: "", HospitalCode: hospitalCode}

	if user.Mobile == "" {
		global.GVA_LOG.Error("获取数据失败!", zap.Any("err", err))
		response.FailWithMessage("获取数据失败", c)
		return
	}

	if qrType != "" {
		user.QrType = qrType
	}

	isReg := service.IsRegister(user)
	userData := model.SysUser{}
	if isReg == 1 {
		if hospitalCode != "" {
			isBind := service.IsBindCode(user)
			if isBind != 1 {
				service.UpdateUserHospitalCode(user.Mobile, hospitalCode)
			}
		}

		userData = service.FindUserByMobile(user.Mobile)

		if userData.Openid == "" {
			service.UpdateUserOpenid(user, int(userData.ID))
		}
	} else {
		_, userData = service.UserRegister(user)
	}

	//医生手机号与登录手机号相同 且 唯一值字段不为空
	if qrType == "1" && user.Mobile == doctorPhone && otherNo != "" {
		fmt.Println(otherNo)
		if service.IsPointsLog(otherNo) == 0 {

			cTime := time.Now()
			//积分流水
			reqPointsLog := model.PointsLog{}
			reqPointsLog.HospitalCode = hospitalCode
			reqPointsLog.UserId = int(userData.ID)
			reqPointsLog.ChangeType = 2
			reqPointsLog.ChangeTime = cTime
			reqPointsLog.ChangeNum = 100
			reqPointsLog.NowPointsNum = userData.PointsNum + reqPointsLog.ChangeNum
			reqPointsLog.Remark = "绑定领取金像奖积分"
			reqPointsLog.OtherNo = otherNo
			reqPointsLog.Source = 1
			reqPointsLog.CreateTime = cTime

			err = service.CreatePointsLog(reqPointsLog)
			if err != nil {
				fmt.Println("CreatePointsLog ERR:", err)
			}

			//修改积分
			err = service.UpdateUserPoints(int(userData.ID), 1, reqPointsLog.ChangeNum)
			if err != nil {
				fmt.Println("UpdateUserPoints ERR:", err)
			}
		}
	}

	j := &middleware.JWT{SigningKey: []byte(global.GVA_CONFIG.JWT.SigningKey)} // 唯一签名
	claims := request.CustomClaims{
		UUID:        userData.UUID,
		ID:          userData.ID,
		AuthorityId: userData.AuthorityId,
		Mobile:      userData.Mobile,
		Openid:      userData.Openid,
		BufferTime:  global.GVA_CONFIG.JWT.BufferTime, // 缓冲时间1天 缓冲时间内会获得新的token刷新令牌 此时一个用户会存在两个有效令牌 但是前端只留一个 另一个会丢失
		StandardClaims: jwt.StandardClaims{
			NotBefore: time.Now().Unix() - 1000,                              // 签名生效时间
			ExpiresAt: time.Now().Unix() + global.GVA_CONFIG.JWT.ExpiresTime, // 过期时间 7天  配置文件
			Issuer:    "qmPlus",                                              // 签名的发行者
		},
	}
	token, err := j.CreateToken(claims)
	if err != nil {
		global.GVA_LOG.Error("获取token失败!", zap.Any("err", err))
		response.FailWithMessage("获取token失败", c)
		return
	}

	response.OkWithDetailed(response.SysUserResponse{User: userData, Token: token, QrData: qrData}, "成功", c)
}

func Register(c *gin.Context) {
	var r request.MobileRegisterReq
	_ = c.ShouldBindJSON(&r)
	var err error

	hospitalCode := r.HospitalCode

	user := model.SysUser{Mobile: r.Mobile, Openid: "", HospitalCode: hospitalCode, RegType: r.RegType}

	isReg := service.IsRegister(user)
	userData := model.SysUser{}
	if isReg == 1 {
		if hospitalCode != "" {
			isBind := service.IsBindCode(user)
			if isBind != 1 {
				service.UpdateUserHospitalCode(user.Mobile, hospitalCode)
			}
		}

		userData = service.FindUserByMobile(user.Mobile)
	} else {
		_, userData = service.UserRegister(user)
	}

	j := &middleware.JWT{SigningKey: []byte(global.GVA_CONFIG.JWT.SigningKey)} // 唯一签名
	claims := request.CustomClaims{
		UUID:        userData.UUID,
		ID:          userData.ID,
		AuthorityId: userData.AuthorityId,
		Mobile:      userData.Mobile,
		Openid:      userData.Openid,
		BufferTime:  global.GVA_CONFIG.JWT.BufferTime, // 缓冲时间1天 缓冲时间内会获得新的token刷新令牌 此时一个用户会存在两个有效令牌 但是前端只留一个 另一个会丢失
		StandardClaims: jwt.StandardClaims{
			NotBefore: time.Now().Unix() - 1000,                              // 签名生效时间
			ExpiresAt: time.Now().Unix() + global.GVA_CONFIG.JWT.ExpiresTime, // 过期时间 7天  配置文件
			Issuer:    "qmPlus",                                              // 签名的发行者
		},
	}
	token, err := j.CreateToken(claims)
	if err != nil {
		global.GVA_LOG.Error("获取token失败!", zap.Any("err", err))
		response.FailWithMessage("获取token失败", c)
		return
	}

	response.OkWithDetailed(response.SysUserResponse{User: userData, Token: token, QrData: response.QrData{}}, "成功", c)
}

func SetUserBind(c *gin.Context) {
	var r request.MobileLogin
	_ = c.ShouldBindJSON(&r)
	var err error

	userId := int(getUserID(c))

	err, userInfo := service.FindUserById(userId)

	hospitalCode := ""
	doctorPhone := ""
	otherNo := ""

	if r.Scene != "" {
		awardData := strings.Split(r.Scene, ";")
		hospitalCode = awardData[0]
		doctorPhone = awardData[1]
		otherNo = awardData[2]
	} else {
		global.GVA_LOG.Error("获取数据失败!", zap.Any("err", err))
		response.FailWithMessage("获取数据失败", c)
		return
	}

	user := model.SysUser{Mobile: userInfo.Mobile, HospitalCode: hospitalCode}

	if user.Mobile == "" {
		global.GVA_LOG.Error("获取数据失败!", zap.Any("err", err))
		response.FailWithMessage("获取数据失败", c)
		return
	}
	isReg := service.IsRegister(user)
	userData := model.SysUser{}
	if isReg == 1 {
		isBind := service.IsBindCode(user)
		if isBind != 1 {
			service.UpdateUserHospitalCode(user.Mobile, user.HospitalCode)
		}
		userData = service.FindUserByMobile(user.Mobile)
	} else {
		_, userData = service.UserRegister(user)
	}

	//医生手机号与登录手机号相同 且 唯一值字段不为空
	if user.Mobile == doctorPhone && otherNo != "" {
		fmt.Println(otherNo)
		if service.IsPointsLog(otherNo) == 0 {

			cTime := time.Now()
			//积分流水
			reqPointsLog := model.PointsLog{}
			reqPointsLog.HospitalCode = user.HospitalCode
			reqPointsLog.UserId = int(userData.ID)
			reqPointsLog.ChangeType = 2
			reqPointsLog.ChangeTime = cTime
			reqPointsLog.ChangeNum = 100
			reqPointsLog.NowPointsNum = userData.PointsNum + reqPointsLog.ChangeNum
			reqPointsLog.Remark = "绑定领取金像奖积分"
			reqPointsLog.OtherNo = otherNo
			reqPointsLog.Source = 1
			reqPointsLog.CreateTime = cTime

			err = service.CreatePointsLog(reqPointsLog)
			if err != nil {
				fmt.Println("CreatePointsLog", err)
			}

			//修改积分
			err = service.UpdateUserPoints(int(userData.ID), 1, reqPointsLog.ChangeNum)
			if err != nil {
				fmt.Println("UpdateUserPoints", err)
			}
		}
	}

	response.OkWithMessage("修改成功", c)
	return
}

func GetOpenid(c *gin.Context) {
	var r request.MobileLogin
	_ = c.ShouldBindJSON(&r)

	if r.UserType == 0 {
		r.UserType = 1
	}

	err, wxReply := utils.GetOpenid(r)
	if err != nil {
		global.GVA_LOG.Error("获取失败!", zap.Any("err", err))
		response.FailWithMessage("获取失败", c)
		return
	}

	response.OkWithData(gin.H{"openid": wxReply}, c)
}

// 从Gin的Context中获取从jwt解析出来的用户ID
func getUserID(c *gin.Context) uint {
	if claims, exists := c.Get("claims"); !exists {
		//global.GVA_LOG.Error("从Gin的Context中获取从jwt解析出来的用户ID失败, 请检查路由是否使用jwt中间件!")
		return 1
	} else {
		waitUse := claims.(*request.CustomClaims)
		return waitUse.ID
	}
}

// @Tags mobile
// @Summary 用户信息修改
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body model.SysUserAuthe true "用户信息修改"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"创建成功"}"
// @Router /mobile/updateUser [post]
func UpdateUser(c *gin.Context) {
	var req request.UpdateUserReq
	_ = c.ShouldBindJSON(&req)

	userId := int(getUserID(c))

	user := model.SysUser{HeaderImg: req.HeaderImg, NickName: req.NickName}
	err := service.UpdateUser(user, userId)

	if err != nil {
		fmt.Println(err)
		response.FailWithMessage("修改失败!", c)
		return
	}

	response.OkWithMessage("修改成功", c)
	return
}

// @Tags mobile
// @Summary 用户认证详情
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Success 200 {string} string "{"success":true,"data":{},"msg":"创建成功"}"
// @Router /mobile/userAutheInfo [post]
func UserAutheInfo(c *gin.Context) {
	userId := getUserID(c)
	var reply request.GetUserInfoReply
	var err error

	if service.IsAuthe(int(userId)) == 1 {
		err, reply = service.UserAutheInfo(userId)
		if err != nil {
			global.GVA_LOG.Error("获取失败!", zap.Any("err", err))
			response.FailWithMessage("获取失败", c)
			return
		}
	}

	//积分信息
	err, userData := service.GetUserInfo(userId)
	if err != nil {
		global.GVA_LOG.Error("获取失败!", zap.Any("err", err))
		response.FailWithMessage("获取失败", c)
		return
	}

	reply.UserId = int(userId)
	reply.PointsNum = userData.PointsNum

	response.OkWithData(gin.H{"reply": reply}, c)
	return
}

// @Tags mobile
// @Summary 身份认证
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body model.SysUserAuthe true "身份认证"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"创建成功"}"
// @Router /mobile/createUserAuthe [post]
func CreateUserAuthe(c *gin.Context) {
	var req model.SysUserAuthe
	_ = c.ShouldBindJSON(&req)

	req.UserId = int(getUserID(c))

	user := model.SysUserAuthe{UserId: req.UserId}
	isYes := service.IsUserAuthe(user)

	if isYes == 1 {
		service.DeleteUserAuthe(req.UserId)
	}

	err := service.CreateUserAuthe(req)
	if err != nil {
		response.FailWithMessage("创建失败!", c)
		return
	}

	response.OkWithMessage("创建成功", c)
	return
}

// @Tags mobile
// @Summary 省市区获取
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Success 200 {string} string "{"success":true,"data":{},"msg":"成功"}"
// @Router /mobile/getRegoinList [post]
func GetRegoinList(c *gin.Context) {
	if err, regionList := service.GetRegion(); err != nil {
		global.GVA_LOG.Error("设置失败!", zap.Any("err", err))
		response.FailWithMessage("设置失败", c)
	} else {
		reply := utils.GetMenu(regionList, 0)
		response.OkWithDetailed(gin.H{"region": reply}, "设置成功", c)
	}
}
