package service

import (
	"fmt"
	"iot_manager_service/app/system/dao"
	"iot_manager_service/app/system/model"
	"iot_manager_service/util/cache"
	"iot_manager_service/util/common"
	"iot_manager_service/util/logger"
	"strconv"
)

// 角色管理服务
var RoleService = new(roleService)

type roleService struct{}

func (s *roleService) Get(id int64) (*dao.Role, error) {
	role := &dao.Role{
		ID: id,
	}
	err := role.Get()
	if err != nil {
		return nil, err
	}
	return role, nil
}

func (s *roleService) List(roleName, tenantId, roleAlias string, current, size int) ([]dao.Role, error) {
	role := &dao.Role{}
	offset := (current - 1) * size
	limit := size
	if roleName != "" {
		role.RoleName = roleName
	}
	if tenantId != "" {
		role.TenantId = tenantId
	}
	if roleAlias != "" {
		role.RoleAlias = roleAlias
	}

	roles, err := role.GetRoles(offset, limit)
	if err != nil {
		return nil, err
	}
	return roles, nil
}

func (s *roleService) Tree() (*model.RspRoleTree, error) {
	role := &dao.Role{}
	roles, err := role.GetAll()

	if err != nil {
		return nil, err
	}
	rsp := &model.RspRoleTree{}
	//上级角色——多个下级角色数组
	tmp := make(map[int64][]dao.Role)
	for _, role := range roles {
		childes, isExist := tmp[role.ParentId]
		if isExist {
			childes = append(childes, role)
			tmp[role.ParentId] = childes
		} else {
			tmp[role.ParentId] = []dao.Role{role}
		}
	}

	if len(tmp) == 0 {
		return nil, nil
	}
	roots, _ := tmp[0]
	rsp.RoleDetails = dfs(rsp.RoleDetails, roots, tmp)

	return rsp, nil
}

func dfs(result []model.RoleDetail, roles []dao.Role, tmp map[int64][]dao.Role) []model.RoleDetail {
	if len(roles) == 0 {
		return nil
	}
	for _, child := range roles {
		id := strconv.FormatInt(child.ID, 10)
		parentId := strconv.FormatInt(child.ParentId, 10)
		detail := model.RoleDetail{
			ID:       id,
			ParentId: parentId,
			Title:    child.RoleName,
			Key:      id,
			Value:    id,
		}
		childes, isExist := tmp[child.ID]
		if isExist {
			detail.HasChildren = true
			detail.Children = dfs([]model.RoleDetail{}, childes, tmp)
			result = append(result, detail)
		} else {
			detail.HasChildren = false
			result = append(result, detail)
		}
	}
	return result
}

func (s *roleService) Submit(req dao.Role) *common.Errors {
	role := &req
	if role.ID == 0 {
		err := role.Save()
		if err != nil {
			return common.FailResponse(err.Error(), nil)
		}
		return common.SuccessResponse(common.Succeeded, nil)
	}
	err := role.Update()
	if err != nil {
		return common.FailResponse(err.Error(), nil)
	}
	return common.SuccessResponse(common.Succeeded, nil)
}

func (s *roleService) GetList() ([]dao.Role, error) {
	role := &dao.Role{}
	roles, err := role.GetAll()
	if err != nil {
		return nil, err
	}
	return roles, nil
}

func (s *roleService) Remove(id int64) *common.Errors {
	role := &dao.Role{
		ID:        id,
		IsDeleted: 1,
	}

	queryRole := &dao.Role{
		ParentId:  id,
		IsDeleted: 0,
	}
	if queryRole.IsExistChild() {
		return common.FailResponse(model.ExistChild, nil)
	}

	err := role.Remove()
	if err != nil {
		return common.FailResponse(err.Error(), nil)
	}
	return nil
}

func (s *roleService) Grant(req *model.ReqRoleGrant) error {
	roleIds := common.StringToInt64Array(req.RoleIds)
	//todo 数据权限 接口权限
	menuIds := common.StringToInt64Array(req.MenuIds)
	menuErr := RoleMenuService.UpdateRoleMenus(roleIds, menuIds)
	return menuErr
}

const RoleNameKey = "%d:sys:role_name:%d"

func (s *roleService) GetRoleName(tenantId int, roleId int64) string {
	var name string
	key := fmt.Sprintf(RoleNameKey, tenantId, roleId)
	name, err := cache.Redis.Get(key).Result()
	if err != nil {
		role := &dao.Role{ID: roleId}
		if err := role.GetRole(); err != nil {
			logger.Logger.Errorf("GetRole err = %s \n", err)
		} else {
			name = role.RoleName
			cache.Redis.Set(key, name, -1)
		}
	}
	return name
}