package api

import (
	"fmt"
	"gitee.ltd/lxh/logger/log"
	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
	"github.com/mojocn/base64Captcha"
	"time"
	"wireguard-ui/component"
	"wireguard-ui/http/param"
	"wireguard-ui/http/response"
	"wireguard-ui/http/vo"
	"wireguard-ui/service"
	"wireguard-ui/utils"
)

type LoginApi struct{}

func Login() LoginApi {
	return LoginApi{}
}

// Captcha
// @description: 获取验证码
// @receiver login
// @param c
func (LoginApi) Captcha(c *gin.Context) {
	math := base64Captcha.DriverMath{Height: 120, Width: 480, Fonts: []string{"ApothecaryFont.ttf", "3Dumb.ttf"}}
	mathDriver := math.ConvertFonts()

	capt := base64Captcha.NewCaptcha(mathDriver, component.Captcha{})

	id, base64Str, _, err := capt.Generate()
	if err != nil {
		response.R(c).FailedWithError(fmt.Errorf("生成验证码失败: %s", err.Error()))
		return
	}

	response.R(c).OkWithData(map[string]any{
		"id":      id,
		"captcha": base64Str,
	})
}

// Login
// @description: 登陆
// @receiver login
// @param c
func (LoginApi) Login(c *gin.Context) {
	var p param.Login
	if err := c.ShouldBind(&p); err != nil {
		response.R(c).Validator(err)
		return
	}

	// 验证验证码是否正确
	ok := component.Captcha{}.Verify(p.CaptchaId, p.CaptchaCode, true)
	if !ok {
		response.R(c).FailedWithError("验证码错误")
		return
	}

	// 验证码正确，查询用户信息
	user, err := service.User().GetUserByAccount(p.Account)
	if err != nil {
		response.R(c).FailedWithError("获取用户信息失败")
		return
	}

	// 对比密码
	if !utils.Password().ComparePassword(user.Password, p.Password) {
		response.R(c).FailedWithError("密码错误")
		return
	}

	secret := component.JWT().GenerateSecret(p.Password, uuid.NewString(), time.Now().Local().String())
	// 生成token
	token, expireAt, err := component.JWT().GenerateToken(user.Id, secret, "http")
	if err != nil {
		log.Errorf("用户[%s]生成token失败: %v", user.Account, err.Error())
		response.R(c).FailedWithError("登陆失败！")
		return
	}

	c.Writer.Header().Set("X-TOKEN", secret)
	response.R(c).OkWithData(map[string]any{
		"token":    token,
		"type":     "Bearer",
		"expireAt": expireAt,
	})
}

// Logout
// @description: 退出登陆
// @receiver LoginApi
// @param c
func (LoginApi) Logout(c *gin.Context) {
	loginUser, ok := c.Get("user")
	if !ok {
		response.R(c).AuthorizationFailed("未登陆")
		return
	}

	if err := component.JWT().Logout(loginUser.(*vo.User).Id); err != nil {
		response.R(c).FailedWithError("退出登陆失败")
		return
	}

	response.R(c).OK()
}
