package service

import (
	"errors"
	"fmt"

	"nms_nbi/features/sys_role/model"
	sysrolemenu "nms_nbi/features/sys_role_menu"
	sysuserrole "nms_nbi/features/sys_user_role"
)

// 实例化服务层 ServiceSysRole 结构体
var NewServiceSysRole = &ServiceSysRole{
	sysRoleRepository:     NewRepoSysRole,
	sysUserRoleRepository: sysuserrole.NewRepoSysUserRole,
	sysRoleMenuRepository: sysrolemenu.NewRepoSysRoleMenu,
}

// ServiceSysRole 角色 服务层处理
type ServiceSysRole struct {
	// 角色服务
	sysRoleRepository *RepoSysRole
	//  用户与角色关联服务
	sysUserRoleRepository *sysuserrole.RepoSysUserRole
	// 角色与菜单关联服务
	sysRoleMenuRepository *sysrolemenu.RepoSysRoleMenu
}

// SelectRolePage 根据条件分页查询角色数据
func (r *ServiceSysRole) SelectRolePage(query map[string]any) map[string]any {
	return r.sysRoleRepository.SelectRolePage(query)
}

// SelectRoleList 根据条件查询角色数据
func (r *ServiceSysRole) SelectRoleList(sysRole model.SysRole) []model.SysRole {
	return r.sysRoleRepository.SelectRoleList(sysRole)
}

// SelectRoleListByUserId 根据用户ID获取角色选择框列表
func (r *ServiceSysRole) SelectRoleListByUserId(userId string) []model.SysRole {
	return r.sysRoleRepository.SelectRoleListByUserId(userId)
}

// SelectRoleById 通过角色ID查询角色
func (r *ServiceSysRole) SelectRoleById(roleId string) model.SysRole {
	if roleId == "" {
		return model.SysRole{}
	}
	posts := r.sysRoleRepository.SelectRoleByIds([]string{roleId})
	if len(posts) > 0 {
		return posts[0]
	}
	return model.SysRole{}
}

// UpdateRole 修改角色信息
func (r *ServiceSysRole) UpdateRole(sysRole model.SysRole) int64 {
	rows := r.sysRoleRepository.UpdateRole(sysRole)
	if rows > 0 {
		// 删除角色与菜单关联
		r.sysRoleMenuRepository.DeleteRoleMenu([]string{sysRole.RoleID})
		if len(sysRole.MenuIds) > 0 {
			r.insertRoleMenu(sysRole.RoleID, sysRole.MenuIds)
		}
	}
	return rows
}

// InsertRole 新增角色信息
func (r *ServiceSysRole) InsertRole(sysRole model.SysRole) string {
	insertId := r.sysRoleRepository.InsertRole(sysRole)
	if insertId != "" && len(sysRole.MenuIds) > 0 {
		r.insertRoleMenu(insertId, sysRole.MenuIds)
	}
	return insertId
}

// insertRoleMenu 新增角色菜单信息
func (r *ServiceSysRole) insertRoleMenu(roleId string, menuIds []string) int64 {
	if roleId == "" || len(menuIds) <= 0 {
		return 0
	}

	sysRoleMenus := []sysrolemenu.SysRoleMenu{}
	for _, menuId := range menuIds {
		if menuId == "" {
			continue
		}
		sysRoleMenus = append(sysRoleMenus, sysrolemenu.NewSysRoleMenu(roleId, menuId))
	}

	return r.sysRoleMenuRepository.BatchRoleMenu(sysRoleMenus)
}

// DeleteRoleByIds 批量删除角色信息
func (r *ServiceSysRole) DeleteRoleByIds(roleIds []string) (int64, error) {
	// 检查是否存在
	roles := r.sysRoleRepository.SelectRoleByIds(roleIds)
	if len(roles) <= 0 {
		return 0, errors.New("no permission to access role data")
	}
	for _, role := range roles {
		// 检查是否为已删除
		if role.DelFlag == "1" {
			return 0, errors.New(role.RoleID + " The character information has been deleted")
		}
		// 检查分配用户
		userCount := r.sysUserRoleRepository.CountUserRoleByRoleId(role.RoleID)
		if userCount > 0 {
			msg := fmt.Sprintf("[%s] has been assigned to a user and cannot be deleted", role.RoleName)
			return 0, errors.New(msg)
		}
	}
	if len(roles) == len(roleIds) {
		// 删除角色与菜单关联
		r.sysRoleMenuRepository.DeleteRoleMenu(roleIds)
		rows := r.sysRoleRepository.DeleteRoleByIds(roleIds)
		return rows, nil
	}
	return 0, errors.New("failed to delete role information")
}

// CheckUniqueRoleName 校验角色名称是否唯一
func (r *ServiceSysRole) CheckUniqueRoleName(roleName, roleId string) bool {
	uniqueId := r.sysRoleRepository.CheckUniqueRole(model.SysRole{
		RoleName: roleName,
	})
	if uniqueId == roleId {
		return true
	}
	return uniqueId == ""
}

// CheckUniqueRoleKey 校验角色权限是否唯一
func (r *ServiceSysRole) CheckUniqueRoleKey(roleKey, roleId string) bool {
	uniqueId := r.sysRoleRepository.CheckUniqueRole(model.SysRole{
		RoleKey: roleKey,
	})
	if uniqueId == roleId {
		return true
	}
	return uniqueId == ""
}

// DeleteAuthUsers 批量取消授权用户角色
func (r *ServiceSysRole) DeleteAuthUsers(roleId string, userIds []string) int64 {
	return r.sysUserRoleRepository.DeleteUserRoleByRoleId(roleId, userIds)
}

// InsertAuthUsers 批量新增授权用户角色
func (r *ServiceSysRole) InsertAuthUsers(roleId string, userIds []string) int64 {
	if roleId == "" || len(userIds) <= 0 {
		return 0
	}

	sysUserRoles := []sysuserrole.SysUserRole{}
	for _, userId := range userIds {
		if userId == "" {
			continue
		}
		sysUserRoles = append(sysUserRoles, sysuserrole.NewSysUserRole(userId, roleId))
	}

	return r.sysUserRoleRepository.BatchUserRole(sysUserRoles)
}
