package controller

import (
	"be.ems/src/framework/config"
	commonConstants "be.ems/src/framework/constants/common"
	tokenConstants "be.ems/src/framework/constants/token"
	"be.ems/src/framework/i18n"
	"be.ems/src/framework/utils/ctx"
	tokenUtils "be.ems/src/framework/utils/token"
	"be.ems/src/framework/vo"
	"be.ems/src/framework/vo/result"
	libAccount "be.ems/src/lib_features/account"
	commonModel "be.ems/src/modules/common/model"
	commonService "be.ems/src/modules/common/service"
	systemService "be.ems/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) {
	language := ctx.AcceptLanguage(c)
	var loginBody commonModel.LoginBody
	if err := c.ShouldBindJSON(&loginBody); err != nil {
		c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}

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

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

	// 登录用户信息
	loginUser, err := s.accountService.LoginByUsername(loginBody.Username, loginBody.Password)
	if err != nil {
		c.JSON(200, result.ErrMsg(i18n.TKey(language, 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, "app.common.loginSuccess",
			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) {
	language := ctx.AcceptLanguage(c)
	loginUser, err := ctx.LoginUser(c)
	if err != nil {
		c.JSON(401, result.CodeMsg(401, i18n.TKey(language, err.Error())))
		return
	}

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

	loginUser.User.NickName = i18n.TKey(language, loginUser.User.NickName)
	loginUser.User.Remark = i18n.TKey(language, loginUser.User.Remark)
	loginUser.User.Dept.DeptName = i18n.TKey(language, loginUser.User.Dept.DeptName)
	for ri := range loginUser.User.Roles {
		loginUser.User.Roles[ri].RoleName = i18n.TKey(language, loginUser.User.Roles[ri].RoleName)
	}
	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 := ctx.LoginUserToUserID(c)

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

	// 闭包函数处理多语言
	language := ctx.AcceptLanguage(c)
	var converI18n func(language string, arr *[]vo.Router)
	converI18n = func(language string, arr *[]vo.Router) {
		for i := range *arr {
			(*arr)[i].Meta.Title = i18n.TKey(language, (*arr)[i].Meta.Title)
			if len((*arr)[i].Children) > 0 {
				converI18n(language, &(*arr)[i].Children)
			}
		}
	}
	converI18n(language, &buildMenus)

	c.JSON(200, result.OkData(buildMenus))
}

// 系统登出
//
// POST /logout
func (s *AccountController) Logout(c *gin.Context) {
	language := ctx.AcceptLanguage(c)
	tokenStr := ctx.Authorization(c)
	if tokenStr != "" {
		// 存在token时记录退出信息
		userName := tokenUtils.Remove(tokenStr)
		if userName != "" {
			// 当前请求信息
			ipaddr, location := ctx.IPAddrLocation(c)
			os, browser := ctx.UaOsBrowser(c)

			// 创建系统访问记录 退出成功

			s.sysLogLoginService.CreateSysLogLogin(
				userName, commonConstants.STATUS_YES, "app.common.logoutSuccess",
				ipaddr, location, os, browser,
			)
		}
	}

	c.JSON(200, result.OkMsg(i18n.TKey(language, "app.common.logoutSuccess")))
}
