package admin

import (
	"fmt"
	"net/http"
	"time"

	"mini-chat/configs"
	"mini-chat/internal/code"
	"mini-chat/internal/pkg/core"
	"mini-chat/internal/pkg/jwtoken"
	"mini-chat/internal/pkg/utils"
	"mini-chat/internal/pkg/validation"
	"mini-chat/internal/proposal"

	"gorm.io/gorm"
)

type loginRequest struct {
	Username string `json:"username" binding:"required"` // 用户名
	Password string `json:"password" binding:"required"` // 密码 (MD5加密后的密码)
}

type loginResponse struct {
	Token   string `json:"token"`    // 登录成功后颁发的 Token
	IsSuper int32  `json:"is_super"` // 是否是超级管理员(1:是 0:否)
}

// Login 管理员登录
// @Summary 管理员登录
// @Description 管理员登录
// @Tags 管理端.登录
// @Accept json
// @Produce json
// @Param RequestBody body loginRequest true "请求参数"
// @Success 200 {object} loginResponse
// @Failure 400 {object} code.Failure
// @Router /api/admin/login [post]
func (h *handler) Login() core.HandlerFunc {
	return func(ctx core.Context) {
		req := new(loginRequest)
		res := new(loginResponse)
		if err := ctx.ShouldBindJSON(req); err != nil {
			ctx.AbortWithError(core.Error(
				http.StatusBadRequest,
				code.ParamBindError,
				validation.Error(err)),
			)
			return
		}

		// 验证用户是否存在
		info, err := h.readDB.Admin.WithContext(ctx.RequestContext()).Where(h.readDB.Admin.Username.Eq(req.Username)).First()
		if err != nil && err != gorm.ErrRecordNotFound {
			ctx.AbortWithError(core.Error(
				http.StatusBadRequest,
				code.AdminLoginError,
				fmt.Sprintf("%s: %s", code.Text(code.AdminLoginError), err.Error())),
			)
			return
		}

		if err == gorm.ErrRecordNotFound {
			ctx.AbortWithError(core.Error(
				http.StatusBadRequest,
				code.AdminLoginError,
				fmt.Sprintf("%s: %s", code.Text(code.AdminLoginError), "账号不存在，请联系管理员。")),
			)
			return
		}

		// 验证登录状态
		if info.LoginStatus != 1 {
			ctx.AbortWithError(core.Error(
				http.StatusBadRequest,
				code.AdminLoginError,
				fmt.Sprintf("%s：账号已被禁用", code.Text(code.AdminLoginError))),
			)
			return
		}

		// 验证密码
		if !utils.VerifyAdminHashedPassword(info.Password, req.Password) {
			ctx.AbortWithError(core.Error(
				http.StatusBadRequest,
				code.AdminLoginError,
				fmt.Sprintf("%s：用户名或密码错误，请联系管理员。", code.Text(code.AdminLoginError))),
			)
			return
		}

		// 设置 Session 信息
		sessionUserInfo := proposal.SessionUserInfo{
			Id:       info.ID,
			UserName: info.Username,
			NickName: info.Nickname,
			IsSuper:  info.IsSuper,
			Platform: "管理端",
		}

		// 设置载荷数据、有效期，生成 JWT Token String
		tokenString, err := jwtoken.New(configs.Get().JWT.AdminSecret).Sign(sessionUserInfo, 3*24*time.Hour)
		if err != nil {
			ctx.AbortWithError(core.Error(
				http.StatusBadRequest,
				code.AdminLoginError,
				fmt.Sprintf("%s：token 生成失败(%s)", code.Text(code.AdminLoginError), err.Error())),
			)
			return
		}

		info.LastLoginTime = time.Now()
		info.LastLoginIP = utils.GetIP(ctx.Request())
		info.LastLoginHash = utils.MD5(tokenString)
		if err := h.writeDB.Admin.WithContext(ctx.RequestContext()).Save(info); err != nil {
			ctx.AbortWithError(core.Error(
				http.StatusBadRequest,
				code.AdminLoginError,
				fmt.Sprintf("%s：%s", code.Text(code.AdminLoginError), err.Error())),
			)
			return
		}

		res.Token = tokenString
		res.IsSuper = info.IsSuper
		ctx.Payload(res)
	}
}
