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) ([]model.RoleVO, int, 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, counts, err := role.GetRoles(offset, limit)
	var result []model.RoleVO
	var temp model.RoleVO
	for _, v := range roles {
		temp.ID = v.ID
		temp.TenantId = v.TenantId
		temp.ParentId = v.ParentId
		temp.RoleName = v.RoleName
		temp.IsDeleted = v.IsDeleted
		temp.RoleAlias = v.RoleAlias
		temp.Sort = v.Sort
		for _, va := range roles {
			if va.ID == temp.ParentId {
				temp.ParentName = va.RoleName
			}
		}
		result = append(result, temp)
	}
	if err != nil {
		return nil, 0, err
	}
	return result, counts, nil
}

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 {
	//todo 数据权限 接口权限
	roleIds := req.RoleIds
	menuIds := req.MenuIds
	menuErr := RoleMenuService.UpdateRoleMenus(roleIds, menuIds)
	return menuErr
}

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

func (s *roleService) GetRoleName(tenantId string, 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
}

func (s *roleService) GetTree() ([]model.RoleDetail, error) {
	roleDao := dao.Role{ParentId: int64(0)}
	var results []model.RoleDetail
	var temp model.RoleDetail
	//所有role包装为roleDetail
	roles, err := roleDao.GetAll()
	var details []model.RoleDetail
	for _, role := range roles {
		temp.ID = role.ID
		temp.ParentId = role.ParentId
		temp.Title = role.RoleName
		details = append(details, temp)
	}
	topRoles, err := roleDao.GetByParentId()
	for _, v := range topRoles {
		temp.ID = v.ID
		temp.ParentId = v.ParentId
		temp.Title = v.RoleName
		temp.Children, temp.HasChildren = s.getChildren(temp, details)
		results = append(results, temp)
	}
	return results, err
}

func (s *roleService) getChildren(parent model.RoleDetail,
	all []model.RoleDetail) ([]model.RoleDetail, bool) {
	pId := parent.ID
	var children []model.RoleDetail
	for _, v := range all {
		if pId == v.ParentId {
			v.Children, v.HasChildren = s.getChildren(v, all)
			children = append(children, v)
		}
	}
	return children, children != nil
}
