package controller

import (
	"strings"

	"be.ems/src/framework/constants/common"
	"be.ems/src/framework/i18n"
	"be.ems/src/framework/utils/ctx"
	"be.ems/src/framework/vo"
	"be.ems/src/framework/vo/result"
	"be.ems/src/modules/system/model"
	"be.ems/src/modules/system/service"

	"github.com/gin-gonic/gin"
	"github.com/gin-gonic/gin/binding"
)

// 实例化控制层 SysDeptController 结构体
var NewSysDept = &SysDeptController{
	sysDeptService: service.NewSysDeptImpl,
}

// 部门信息
//
// PATH /system/dept
type SysDeptController struct {
	// 部门服务
	sysDeptService service.ISysDept
}

// 部门列表
//
// GET /list
func (s *SysDeptController) List(c *gin.Context) {
	language := ctx.AcceptLanguage(c)
	var querys struct {
		// 部门ID
		DeptID string `json:"deptId"`
		// 父部门ID
		ParentID string `json:"parentId" `
		// 部门名称
		DeptName string `json:"deptName" `
		// 部门状态（0正常 1停用）
		Status string `json:"status"`
	}
	err := c.ShouldBindQuery(&querys)
	if err != nil {
		c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}

	SysDeptController := model.SysDept{
		DeptID:   querys.DeptID,
		ParentID: querys.ParentID,
		DeptName: querys.DeptName,
		Status:   querys.Status,
	}
	dataScopeSQL := ctx.LoginUserToDataScopeSQL(c, "d", "")
	data := s.sysDeptService.SelectDeptList(SysDeptController, dataScopeSQL)

	// 闭包函数处理多语言
	converI18n := func(language string, arr *[]model.SysDept) {
		for i := range *arr {
			(*arr)[i].DeptName = i18n.TKey(language, (*arr)[i].DeptName)
		}
	}
	converI18n(language, &data)

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

// 部门信息
//
// GET /:deptId
func (s *SysDeptController) Info(c *gin.Context) {
	language := ctx.AcceptLanguage(c)
	deptId := c.Param("deptId")
	if deptId == "" {
		c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}
	data := s.sysDeptService.SelectDeptById(deptId)
	if data.DeptID == deptId {
		// 处理多语言
		data.DeptName = i18n.TKey(language, data.DeptName)
		c.JSON(200, result.OkData(data))
		return
	}
	c.JSON(200, result.Err(nil))
}

// 部门新增
//
// POST /
func (s *SysDeptController) Add(c *gin.Context) {
	language := ctx.AcceptLanguage(c)
	var body model.SysDept
	err := c.ShouldBindBodyWith(&body, binding.JSON)
	if err != nil || body.DeptID != "" {
		c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}

	// 父级ID不为0是要检查
	if body.ParentID != "0" {
		deptParent := s.sysDeptService.SelectDeptById(body.ParentID)
		if deptParent.DeptID != body.ParentID {
			// 没有可访问部门数据！
			c.JSON(200, result.ErrMsg(i18n.TKey(language, "dept.noData")))
			return
		}
		if deptParent.Status == common.STATUS_NO {
			// 上级部门【%s】停用，不允许新增
			msg := i18n.TTemplate(language, "dept.errParentStatus", map[string]any{"name": deptParent.DeptName})
			c.JSON(200, result.ErrMsg(msg))
			return
		}
		if deptParent.DelFlag == common.STATUS_YES {
			// 上级部门【%s】已删除，不允许新增
			msg := i18n.TTemplate(language, "dept.errParentDelFlag", map[string]any{"name": deptParent.DeptName})
			c.JSON(200, result.ErrMsg(msg))
			return
		}
		body.Ancestors = deptParent.Ancestors + "," + body.ParentID
	} else {
		body.Ancestors = "0"
	}

	// 检查同级下名称唯一
	uniqueDeptName := s.sysDeptService.CheckUniqueDeptName(body.DeptName, body.ParentID, "")
	if !uniqueDeptName {
		// 部门新增【%s】失败，部门名称已存在
		msg := i18n.TTemplate(language, "dept.errNameExists", map[string]any{"name": body.DeptName})
		c.JSON(200, result.ErrMsg(msg))
		return
	}

	body.CreateBy = ctx.LoginUserToUserName(c)
	insertId := s.sysDeptService.InsertDept(body)
	if insertId != "" {
		c.JSON(200, result.Ok(nil))
		return
	}
	c.JSON(200, result.Err(nil))
}

// 部门修改
//
// PUT /
func (s *SysDeptController) Edit(c *gin.Context) {
	language := ctx.AcceptLanguage(c)
	var body model.SysDept
	err := c.ShouldBindBodyWith(&body, binding.JSON)
	if err != nil || body.DeptID == "" {
		c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}

	// 上级部门不能选自己
	if body.DeptID == body.ParentID {
		// 部门修改【%s】失败，上级部门不能是自己
		msg := i18n.TTemplate(language, "dept.errParentID", map[string]any{"name": body.DeptName})
		c.JSON(200, result.ErrMsg(msg))
		return
	}

	// 检查数据是否存在
	deptInfo := s.sysDeptService.SelectDeptById(body.DeptID)
	if deptInfo.DeptID != body.DeptID {
		// 没有可访问部门数据！
		c.JSON(200, result.ErrMsg(i18n.TKey(language, "dept.noData")))
		return
	}
	// 父级ID不为0是要检查
	if body.ParentID != "0" {
		deptParent := s.sysDeptService.SelectDeptById(body.ParentID)
		if deptParent.DeptID != body.ParentID {
			// 没有可访问部门数据！
			c.JSON(200, result.ErrMsg(i18n.TKey(language, "dept.noData")))
			return
		}
	}

	// 检查同级下名称唯一
	uniqueDeptName := s.sysDeptService.CheckUniqueDeptName(body.DeptName, body.ParentID, body.DeptID)
	if !uniqueDeptName {
		// 部门修改【%s】失败，部门名称已存在
		msg := i18n.TTemplate(language, "dept.errNameExists", map[string]any{"name": body.DeptName})
		c.JSON(200, result.ErrMsg(msg))
		return
	}

	// 上级停用需要检查下级是否有在使用
	if body.Status == common.STATUS_NO {
		hasChild := s.sysDeptService.HasChildByDeptId(body.DeptID)
		if hasChild > 0 {
			// 该部门包含未停用的子部门数量：%d
			msg := i18n.TTemplate(language, "dept.errHasChildUse", map[string]any{"num": hasChild})
			c.JSON(200, result.ErrMsg(msg))
			return
		}
	}

	// 多语言非原始值
	i18nValue := i18n.TKey(language, deptInfo.DeptName)
	if i18nValue != deptInfo.DeptName {
		i18n.UpdateKeyValue(language, deptInfo.DeptName, body.DeptName)
		body.DeptName = deptInfo.DeptName
	}

	body.UpdateBy = ctx.LoginUserToUserName(c)
	rows := s.sysDeptService.UpdateDept(body)
	if rows > 0 {
		c.JSON(200, result.Ok(nil))
		return
	}
	c.JSON(200, result.Err(nil))
}

// 部门删除
//
// DELETE /:deptId
func (s *SysDeptController) Remove(c *gin.Context) {
	language := ctx.AcceptLanguage(c)
	deptId := c.Param("deptId")
	if deptId == "" {
		c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}

	// 检查数据是否存在
	dept := s.sysDeptService.SelectDeptById(deptId)
	if dept.DeptID != deptId {
		// 没有可访问部门数据！
		c.JSON(200, result.ErrMsg(i18n.TKey(language, "dept.noData")))
		return
	}

	// 检查是否存在子部门
	hasChild := s.sysDeptService.HasChildByDeptId(deptId)
	if hasChild > 0 {
		// 不允许删除，存在子部门数：%d
		msg := i18n.TTemplate(language, "dept.errHasChildUse", map[string]any{"num": hasChild})
		c.JSON(200, result.ErrMsg(msg))
		return
	}

	// 检查是否分配给用户
	existUser := s.sysDeptService.CheckDeptExistUser(deptId)
	if existUser > 0 {
		// 不允许删除，部门已分配给用户数：%d
		msg := i18n.TTemplate(language, "dept.errHasUserUse", map[string]any{"num": existUser})
		c.JSON(200, result.ErrMsg(msg))
		return
	}

	rows := s.sysDeptService.DeleteDeptById(deptId)
	if rows > 0 {
		// 删除成功：%d
		msg := i18n.TTemplate(language, "app.common.deleteSuccess", map[string]any{"num": rows})
		c.JSON(200, result.OkMsg(msg))
		return
	}
	c.JSON(200, result.Err(nil))
}

// 部门列表（排除节点）
//
// GET /list/exclude/:deptId
func (s *SysDeptController) ExcludeChild(c *gin.Context) {
	language := ctx.AcceptLanguage(c)
	deptId := c.Param("deptId")
	if deptId == "" {
		c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}

	dataScopeSQL := ctx.LoginUserToDataScopeSQL(c, "d", "")
	data := s.sysDeptService.SelectDeptList(model.SysDept{}, dataScopeSQL)

	// 过滤排除节点
	filtered := make([]model.SysDept, 0)
	for _, dept := range data {
		hasAncestor := false
		ancestorList := strings.Split(dept.Ancestors, ",")
		for _, ancestor := range ancestorList {
			if ancestor == deptId {
				hasAncestor = true
				break
			}
		}
		if !(dept.DeptID == deptId || hasAncestor) {
			dept.DeptName = i18n.TKey(language, dept.DeptName)
			filtered = append(filtered, dept)
		}
	}
	c.JSON(200, result.OkData(filtered))
}

// 部门树结构列表
//
// GET /treeSelect
func (s *SysDeptController) TreeSelect(c *gin.Context) {
	language := ctx.AcceptLanguage(c)
	var querys struct {
		// 部门ID
		DeptID string `json:"deptId"`
		// 父部门ID
		ParentID string `json:"parentId" `
		// 部门名称
		DeptName string `json:"deptName" `
		// 部门状态（0正常 1停用）
		Status string `json:"status"`
	}
	err := c.ShouldBindQuery(&querys)
	if err != nil {
		c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}

	SysDeptController := model.SysDept{
		DeptID:   querys.DeptID,
		ParentID: querys.ParentID,
		DeptName: querys.DeptName,
		Status:   querys.Status,
	}
	dataScopeSQL := ctx.LoginUserToDataScopeSQL(c, "d", "")
	deptTreeSelect := s.sysDeptService.SelectDeptTreeSelect(SysDeptController, dataScopeSQL)

	// 闭包函数处理多语言
	var converI18n func(language string, arr *[]vo.TreeSelect)
	converI18n = func(language string, arr *[]vo.TreeSelect) {
		for i := range *arr {
			(*arr)[i].Label = i18n.TKey(language, (*arr)[i].Label)
			if len((*arr)[i].Children) > 0 {
				converI18n(language, &(*arr)[i].Children)
			}
		}
	}
	converI18n(language, &deptTreeSelect)

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

// 部门树结构列表（指定角色）
//
// GET /roleDeptTreeSelect/:roleId
func (s *SysDeptController) RoleDeptTreeSelect(c *gin.Context) {
	language := ctx.AcceptLanguage(c)
	roleId := c.Param("roleId")
	if roleId == "" {
		c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}

	dataScopeSQL := ctx.LoginUserToDataScopeSQL(c, "d", "")
	deptTreeSelect := s.sysDeptService.SelectDeptTreeSelect(model.SysDept{}, dataScopeSQL)
	checkedKeys := s.sysDeptService.SelectDeptListByRoleId(roleId)

	// 闭包函数处理多语言
	var converI18n func(language string, arr *[]vo.TreeSelect)
	converI18n = func(language string, arr *[]vo.TreeSelect) {
		for i := range *arr {
			(*arr)[i].Label = i18n.TKey(language, (*arr)[i].Label)
			if len((*arr)[i].Children) > 0 {
				converI18n(language, &(*arr)[i].Children)
			}
		}
	}
	converI18n(language, &deptTreeSelect)

	c.JSON(200, result.OkData(map[string]any{
		"depts":       deptTreeSelect,
		"checkedKeys": checkedKeys,
	}))
}
