package system

import (
	"sundynix-go/global"
	"sundynix-go/model/commom/response"
	"sundynix-go/model/system"
	systemReq "sundynix-go/model/system/request"
	systemRes "sundynix-go/model/system/response"
	"sundynix-go/utils/auth"

	"github.com/gin-gonic/gin"
	"github.com/mojocn/base64Captcha"
	"go.uber.org/zap"
)

var store = base64Captcha.DefaultMemStore

type AuthApi struct{}

// Login
// @Tags      登录相关
// @Summary   pc登录
// @accept    application/json
// @Produce   application/json
// @Param     data  body  systemReq.Login  true "用户名, 密码, 验证码,验证码id"
// @Success   200   {object}  response.Response{msg=string}  "登录成功"
// @Router    /auth/login [post]
func (a *AuthApi) Login(c *gin.Context) {
	var l systemReq.Login
	err := c.ShouldBindJSON(&l)
	if err != nil {
		response.FailWithMsg(err.Error(), c)
		return
	}
	if l.CaptchaId != "" && l.Captcha != "" && store.Verify(l.CaptchaId, l.Captcha, true) {
		u := &system.User{Account: l.Account, Password: l.Password}
		user, err := userService.Login(u)
		if err != nil {
			global.Logger.Error("登录失败! 用户名不存在或者密码错误!", zap.Error(err))
			response.FailWithMsg("用户名不存在或者密码错误", c)
			return
		}
		a.GetToken(c, *user)
		return
	}
	response.FailWithMsg("验证码错误", c)
}

// Logout
// @Tags      登录相关
// @Summary   pc登出
// @Security  ApiKeyAuth
// @Produce   application/json
// @Success   200   {object}  response.Response{msg=string}  "登出成功"
// @Router    /auth/logout [get]
func (a *AuthApi) Logout(c *gin.Context) {
	token := auth.GetToken(c)
	userId := auth.GetUserId(c)
	err := jwtService.PutBlacklist(userId, token)
	if err != nil {
		global.Logger.Error("登出失败!", zap.Error(err))
		response.FailWithMsg("登出失败", c)
		return
	}
	auth.ClearToken(c)
	response.OkWithMsg("登出成功", c)

}

// Captcha
// @Tags      登录相关
// @Summary   获取验证码
// @Produce   application/json
// @Success   200   {object}  response.Response{data=systemRes.CaptchaRes}  "获取验证码"
// @Router    /auth/captcha [get]
func (a *AuthApi) Captcha(c *gin.Context) {
	var driver = base64Captcha.DriverString{
		Height:          80,
		Width:           240,
		NoiseCount:      2,
		ShowLineOptions: 4,
		Length:          4,
		Source:          "1234567890",
	}

	cp := base64Captcha.NewCaptcha(&driver, store)
	id, b64s, _, err := cp.Generate()
	if err != nil {
		global.Logger.Error("GenerateCaptcha err", zap.Error(err))
		response.FailWithMsg("GenerateCaptcha err", c)
		return
	}
	response.OkWithData(systemRes.CaptchaRes{
		CaptchaId: id,
		Captcha:   b64s,
	}, c)
}

func (a *AuthApi) GetToken(c *gin.Context, user system.User) {
	token, claims, err := auth.GetLoginToken(&user)
	if err != nil {
		global.Logger.Error("GetToken err", zap.Error(err))
		response.FailWithMsg("GetToken err", c)
	}
	response.OkWithData(systemRes.LoginResponse{
		ExpiresAt: claims.RegisteredClaims.ExpiresAt.Unix() * 1000,
		Token:     token,
		User:      user,
	}, c)
}

// MiniLogin
// @Tags      登录相关
// @Summary   小程序登录
// @Produce   application/json
// @Param     code query string true "code"
// @Success   200   {object}  response.Response{data=systemRes.LoginResponse}  "小程序登录"
// @Router    /auth/miniLogin [get]
func (a *AuthApi) MiniLogin(c *gin.Context) {
	jsCode := c.Query("code")
	user, err := userService.MiniLogin(jsCode)
	if err != nil {
		global.Logger.Error("登录失败!", zap.Error(err))
		response.FailWithMsg("登录失败", c)
		return
	}
	a.GetToken(c, *user)
	return
}

// GetPhone
// @Tags      登录相关
// @Summary   获取手机号
// @Produce   application/json
// @Param     code query string true "code"
// @Param     openId query string true "openId"
// @Router    /auth/getPhone [get]
func (a *AuthApi) GetPhone(c *gin.Context) {
	jsCode := c.Query("code")
	openId := c.Query("openId")
	user, err := userService.LoginByPhone(jsCode, openId)
	if err != nil {
		global.Logger.Error("登录失败!", zap.Error(err))
		response.FailWithMsg("登录失败", c)
		return
	}
	response.OkWithData(user, c)
}

// GetLocation
// @Tags      登录相关
// @Summary   获取位置信息
// @Produce   application/json
// @Param     longitude query string true "longitude"
// @Param     latitude query string true "latitude"
// @Router    /auth/getLocation [get]
func (a *AuthApi) GetLocation(c *gin.Context) {
	longitude := c.Query("longitude") //经度
	latitude := c.Query("latitude")
	location, err := userService.GetLocation(longitude, latitude)
	if err != nil {
		global.Logger.Error("获取位置信息失败!", zap.Error(err))
		response.FailWithMsg("获取位置信息失败", c)
		return
	}
	response.OkWithData(location, c)
}

// GetWeather
// @Tags      登录相关
// @Summary   获取天气信息
// @Produce   application/json
// @Param     adcode query string true "adcode"
// @Router    /auth/getWeather [get]
func (a *AuthApi) GetWeather(c *gin.Context) {
	value := c.Query("adcode")
	weather, err := userService.GetWeather(value)
	if err != nil {
		global.Logger.Error("获取天气信息失败!", zap.Error(err))
		response.FailWithMsg("获取天气信息失败", c)
		return
	}
	response.OkWithData(weather, c)

}
