package controller

import (
	"ems.agt/src/framework/config"
	commonConstants "ems.agt/src/framework/constants/common"
	tokenConstants "ems.agt/src/framework/constants/token"
	ctxUtils "ems.agt/src/framework/utils/ctx"
	tokenUtils "ems.agt/src/framework/utils/token"
	"ems.agt/src/framework/vo/result"
	libAccount "ems.agt/src/lib_features/account"
	commonModel "ems.agt/src/modules/common/model"
	commonService "ems.agt/src/modules/common/service"
	systemService "ems.agt/src/modules/system/service"
	"github.com/gin-gonic/gin"
)

// 实例化控制层 AccountController 结构体
var NewAccount = &AccountController{
	accountService:     commonService.NewAccountImpl,
	sysLogLoginService: systemService.NewSysLogLoginImpl,
}

// 账号身份操作处理
//
// PATH /
type AccountController struct {
	// 账号身份操作服务
	accountService commonService.IAccount
	// 系统登录访问
	sysLogLoginService systemService.ISysLogLogin
}

// 系统登录
//
// POST /login
func (s *AccountController) Login(c *gin.Context) {
	var loginBody commonModel.LoginBody
	if err := c.ShouldBindJSON(&loginBody); err != nil {
		c.JSON(400, result.CodeMsg(400, "parameter error"))
		return
	}

	// 当前请求信息
	ipaddr, location := ctxUtils.IPAddrLocation(c)
	os, browser := ctxUtils.UaOsBrowser(c)

	// 校验验证码
	err := s.accountService.ValidateCaptcha(
		loginBody.Code,
		loginBody.UUID,
	)
	// 根据错误信息，创建系统访问记录
	if err != nil {
		msg := err.Error() + " " + loginBody.Code
		s.sysLogLoginService.CreateSysLogLogin(
			loginBody.Username, commonConstants.STATUS_NO, msg,
			ipaddr, location, os, browser,
		)
		c.JSON(200, result.ErrMsg(err.Error()))
		return
	}

	// 登录用户信息
	loginUser, err := s.accountService.LoginByUsername(loginBody.Username, loginBody.Password)
	if err != nil {
		c.JSON(200, result.ErrMsg(err.Error()))
		return
	}

	// 生成令牌，创建系统访问记录
	tokenStr := tokenUtils.Create(&loginUser, ipaddr, location, os, browser)
	if tokenStr == "" {
		c.JSON(200, result.Err(nil))
		return
	} else {
		s.accountService.UpdateLoginDateAndIP(&loginUser)
		// 登录成功
		s.sysLogLoginService.CreateSysLogLogin(
			loginBody.Username, commonConstants.STATUS_YES, "Login Successful",
			ipaddr, location, os, browser,
		)
	}

	// 设置登录会话-兼容旧登录方式
	libAccount.SessionToken(loginBody.Username, ipaddr)

	c.JSON(200, result.OkData(map[string]any{
		tokenConstants.RESPONSE_FIELD: tokenStr,
	}))
}

// 登录用户信息
//
// GET /getInfo
func (s *AccountController) Info(c *gin.Context) {
	loginUser, err := ctxUtils.LoginUser(c)
	if err != nil {
		c.JSON(401, result.CodeMsg(401, err.Error()))
		return
	}

	// 角色权限集合，管理员拥有所有权限
	isAdmin := config.IsAdmin(loginUser.UserID)
	roles, perms := s.accountService.RoleAndMenuPerms(loginUser.UserID, isAdmin)

	c.JSON(200, result.OkData(map[string]any{
		"user":        loginUser.User,
		"roles":       roles,
		"permissions": perms,
	}))
}

// 登录用户路由信息
//
// GET /getRouters
func (s *AccountController) Router(c *gin.Context) {
	userID := ctxUtils.LoginUserToUserID(c)

	// 前端路由，管理员拥有所有
	isAdmin := config.IsAdmin(userID)
	buildMenus := s.accountService.RouteMenus(userID, isAdmin)
	c.JSON(200, result.OkData(buildMenus))
}

// 系统登出
//
// POST /logout
func (s *AccountController) Logout(c *gin.Context) {
	tokenStr := ctxUtils.Authorization(c)
	if tokenStr != "" {
		// 存在token时记录退出信息
		userName := tokenUtils.Remove(tokenStr)
		if userName != "" {
			// 当前请求信息
			ipaddr, location := ctxUtils.IPAddrLocation(c)
			os, browser := ctxUtils.UaOsBrowser(c)
			// 创建系统访问记录 退出成功
			s.sysLogLoginService.CreateSysLogLogin(
				userName, commonConstants.STATUS_YES, "Exit successful",
				ipaddr, location, os, browser,
			)
		}
	}

	c.JSON(200, result.OkMsg("Exit successful"))
}
