package api

import (
	"gitee.ltd/lxh/logger/log"
	"github.com/gin-gonic/gin"
	"wireguard-dashboard/client"
	"wireguard-dashboard/component"
	"wireguard-dashboard/constant"
	"wireguard-dashboard/http/param"
	"wireguard-dashboard/model/entity"
	"wireguard-dashboard/model/vo"
	"wireguard-dashboard/repository"
	"wireguard-dashboard/utils"
)

type user struct{}

func UserApi() user {
	return user{}
}

// Login
// @description: 登陆
// @receiver u
// @param c
func (user) Login(c *gin.Context) {
	var p param.Login
	if err := c.ShouldBind(&p); err != nil {
		utils.GinResponse(c).FailedWithErr("参数错误", err)
		return
	}

	// 校验验证码
	pass := component.CaptchaStore{}.Verify(p.CaptchaId, p.CaptchaAnswer, true)
	if !pass {
		utils.GinResponse(c).FailedWithMsg("验证码错误")
		return
	}

	// 校验用户是否存在
	user, err := repository.User().GetUserByAccount(p.Account)
	if err != nil {
		utils.GinResponse(c).FailedWithMsg("账户不存在")
		return
	}

	if user.Status != constant.Normal {
		utils.GinResponse(c).FailedWithMsg("账户状态异常")
		return
	}

	// 校验密码
	if !utils.Password().ComparePassword(user.Password, p.Password) {
		utils.GinResponse(c).FailedWithMsg("密码错误")
		return
	}

	// 生成token
	token, expireTime, err := component.JWT().GenerateToken(user.Id)
	if err != nil {
		utils.GinResponse(c).FailedWithMsg("登陆失败")
		return
	}

	utils.GinResponse(c).OKWithData(map[string]any{
		"token":    token,
		"type":     "Bearer",
		"expireAt": expireTime.Unix(),
	})
}

// Logout
// @description: 退出登陆
// @receiver u
// @param c
func (user) Logout(c *gin.Context) {
	data, ok := c.Get("user")
	if !ok {
		utils.GinResponse(c).FailedWithMsg("你还没有登陆")
		return
	}
	if err := component.JWT().Logout(data.(*entity.User).Id); err != nil {
		log.Errorf("退出登陆失败: %v", err.Error())
		utils.GinResponse(c).FailedWithMsg("退出登陆失败")
		return
	}
	utils.GinResponse(c).OK()
}

// List
// @description: 用户列表
// @receiver u
// @param c
func (user) List(c *gin.Context) {
	var p param.UserList
	if err := c.ShouldBind(&p); err != nil {
		utils.GinResponse(c).FailedWithErr("参数错误", err)
		return
	}

	data, total, err := repository.User().List(p)
	if err != nil {
		utils.GinResponse(c).FailedWithMsg("获取失败")
		return
	}

	utils.GinResponse(c).OkWithPage(data, total, p.Current, p.Size)
}

// GetUser
// @description: 获取登陆用户信息
// @receiver u
// @param c
func (user) GetUser(c *gin.Context) {
	info, ok := c.Get("user")
	if !ok {
		utils.GinResponse(c).FailedWithMsg("获取信息失败")
		return
	}
	data := &vo.User{
		Id:        info.(*entity.User).Id,
		Name:      info.(*entity.User).Name,
		Avatar:    info.(*entity.User).Avatar,
		Account:   info.(*entity.User).Account,
		Email:     info.(*entity.User).Email,
		IsAdmin:   info.(*entity.User).IsAdmin,
		Status:    info.(*entity.User).Status,
		CreatedAt: info.(*entity.User).CreatedAt,
		UpdatedAt: info.(*entity.User).UpdatedAt,
	}
	utils.GinResponse(c).OKWithData(data)
}

// Save
// @description: 新增/更改用户信息
// @receiver u
// @param c
func (user) Save(c *gin.Context) {
	var p param.SaveUser
	if err := c.ShouldBind(&p); err != nil {
		utils.GinResponse(c).FailedWithErr("参数错误", err)
		return
	}

	// 只有新增才会判断
	if p.ID == "" {
		// 判断用户是否已经存在
		var count int64
		if err := client.DB.Model(&entity.User{}).Where("account = ?", p.Account).Count(&count).Error; err != nil {
			utils.GinResponse(c).FailedWithMsg("查询失败")
			return
		}

		if count > 0 {
			utils.GinResponse(c).FailedWithMsg("用户已存在!")
			return
		}
	}

	if err := repository.User().Save(&entity.User{
		Base: entity.Base{
			Id: p.ID,
		},
		Avatar:   p.Avatar,
		Name:     p.Name,
		Account:  p.Account,
		Email:    p.Email,
		Password: p.Password,
		IsAdmin:  p.IsAdmin,
		Status:   p.Status,
	}); err != nil {
		utils.GinResponse(c).FailedWithMsg(err.Error())
		return
	}

	utils.GinResponse(c).OK()
}

// ChangePassword
// @description: 更改密码
// @receiver u
// @param c
func (user) ChangePassword(c *gin.Context) {
	var p param.ChangePassword
	if err := c.ShouldBind(&p); err != nil {
		utils.GinResponse(c).FailedWithErr("参数错误", err)
		return
	}

	user, ok := c.Get("user")
	if !ok {
		utils.GinResponse(c).AuthorizationFailed()
		return
	}

	if !utils.Password().ComparePassword(user.(*entity.User).Password, p.OriginPassword) {
		utils.GinResponse(c).FailedWithMsg("原密码错误")
		return
	}

	// 开始变更密码
	if err := repository.User().ChangePassword(p, user.(*entity.User).Id); err != nil {
		utils.GinResponse(c).FailedWithMsg("更改密码失败")
		return
	}

	utils.GinResponse(c).OK()
}

// ChangeUserState
// @description: 改变用户状态
// @receiver u
// @param c
func (user) ChangeUserState(c *gin.Context) {
	var p param.ChangeUserState
	if err := c.ShouldBind(&p); err != nil {
		utils.GinResponse(c).FailedWithErr("参数错误", err)
		return
	}

	if err := repository.User().ChangeUserState(p); err != nil {
		utils.GinResponse(c).FailedWithMsg("操作失败")
		return
	}

	utils.GinResponse(c).OK()
}