package service

import (
	"strings"

	"be.ems/src/framework/constants/common"
	"be.ems/src/framework/vo"
	"be.ems/src/modules/system/model"
	"be.ems/src/modules/system/repository"
)

// 实例化服务层 SysTenantImpl 结构体
var NewSysTenantImpl = &SysTenantImpl{
	sysTenantRepository:     repository.NewSysTenantImpl,
	sysRoleRepository:       repository.NewSysRoleImpl,
	sysRoleTenantRepository: repository.NewSysRoleTenantImpl,
}

// SysTenantImpl 租户表 服务层处理
type SysTenantImpl struct {
	// 租户服务
	sysTenantRepository repository.ISysTenant
	// 角色服务
	sysRoleRepository repository.ISysRole
	// 角色与租户关联服务
	sysRoleTenantRepository repository.ISysRoleTenant
}

// SelectTenantList 查询租户管理数据
func (r *SysTenantImpl) SelectTenantList(sysTenant model.SysTenant, dataScopeSQL string) []model.SysTenant {
	return r.sysTenantRepository.SelectTenantList(sysTenant, dataScopeSQL)
}

// SelectTenantListByRoleId 根据角色ID查询租户树信息 TODO
func (r *SysTenantImpl) SelectTenantListByRoleId(roleId string) []string {
	roles := r.sysRoleRepository.SelectRoleByIds([]string{roleId})
	if len(roles) > 0 {
		role := roles[0]
		if role.RoleID == roleId {
			return r.sysTenantRepository.SelectTenantListByRoleId(
				role.RoleID,
				role.TenantCheckStrictly == "1",
			)
		}
	}
	return []string{}
}

// SelectTenantById 根据租户ID查询信息
func (r *SysTenantImpl) SelectTenantById(tenantId string) model.SysTenant {
	return r.sysTenantRepository.SelectTenantById(tenantId)
}

// HasChildByTenantId 是否存在子节点
func (r *SysTenantImpl) HasChildByTenantId(tenantId string) int64 {
	return r.sysTenantRepository.HasChildByTenantId(tenantId)
}

// CheckTenantExistUser 查询租户是否存在用户
func (r *SysTenantImpl) CheckTenantExistUser(tenantId string) int64 {
	return r.sysTenantRepository.CheckTenantExistUser(tenantId)
}

// CheckUniqueTenantName 校验同级租户名称是否唯一
func (r *SysTenantImpl) CheckUniqueTenantName(tenantName, parentId, tenantId string) bool {
	uniqueId := r.sysTenantRepository.CheckUniqueTenant(model.SysTenant{
		TenantName: tenantName,
		ParentID:   parentId,
	})
	if uniqueId == tenantId {
		return true
	}
	return uniqueId == ""
}

// CheckUniqueTenantName 校验同级租户名称是否唯一
func (r *SysTenantImpl) IsUniqueTenancy(tenantID, tenancyType, tenancyKey string) bool {
	return r.sysTenantRepository.IsUniqueTenancy(model.SysTenant{
		TenantID:    tenantID,
		TenancyType: tenancyType,
		TenancyKey:  tenancyKey,
	})
}

// InsertTenant 新增租户信息
func (r *SysTenantImpl) InsertTenant(sysTenant model.SysTenant) string {
	return r.sysTenantRepository.InsertTenant(sysTenant)
}

// UpdateTenant 修改租户信息
func (r *SysTenantImpl) UpdateTenant(sysTenant model.SysTenant) int64 {
	parentTenant := r.sysTenantRepository.SelectTenantById(sysTenant.ParentID)
	tenant := r.sysTenantRepository.SelectTenantById(sysTenant.TenantID)
	// 上级与当前租户祖级列表更新
	if parentTenant.TenantID == sysTenant.ParentID && tenant.TenantID == sysTenant.TenantID {
		newAncestors := parentTenant.Ancestors + "," + parentTenant.TenantID
		oldAncestors := tenant.Ancestors
		// 祖级列表不一致时更新
		if newAncestors != oldAncestors {
			sysTenant.Ancestors = newAncestors
			r.updateTenantChildren(sysTenant.TenantID, newAncestors, oldAncestors)
		}
	}
	// 如果该租户是启用状态，则启用该租户的所有上级租户
	if sysTenant.Status == common.STATUS_YES && parentTenant.Status == common.STATUS_NO {
		r.updateTenantStatusNormal(sysTenant.Ancestors)
	}
	return r.sysTenantRepository.UpdateTenant(sysTenant)
}

// updateTenantStatusNormal 修改所在租户正常状态
func (r *SysTenantImpl) updateTenantStatusNormal(ancestors string) int64 {
	if ancestors == "" || ancestors == "0" {
		return 0
	}
	tenantIds := strings.Split(ancestors, ",")
	return r.sysTenantRepository.UpdateTenantStatusNormal(tenantIds)
}

// updateTenantChildren 修改子元素关系
func (r *SysTenantImpl) updateTenantChildren(tenantId, newAncestors, oldAncestors string) int64 {
	childrens := r.sysTenantRepository.SelectChildrenTenantById(tenantId)
	if len(childrens) == 0 {
		return 0
	}
	// 替换父ID
	for i := range childrens {
		child := &childrens[i]
		ancestors := strings.Replace(child.Ancestors, oldAncestors, newAncestors, -1)
		child.Ancestors = ancestors
	}
	return r.sysTenantRepository.UpdateTenantChildren(childrens)
}

// DeleteTenantById 删除租户管理信息
func (r *SysTenantImpl) DeleteTenantById(tenantId string) int64 {
	// 删除角色与租户关联
	r.sysRoleTenantRepository.DeleteTenantRole([]string{tenantId})
	return r.sysTenantRepository.DeleteTenantById(tenantId)
}

// SelectTenantTreeSelect 查询租户树结构信息
func (r *SysTenantImpl) SelectTenantTreeSelect(sysTenant model.SysTenant, dataScopeSQL string) []vo.TreeSelect {
	sysTenants := r.sysTenantRepository.SelectTenantList(sysTenant, dataScopeSQL)
	tenants := r.parseDataToTree(sysTenants)
	tree := make([]vo.TreeSelect, 0)
	for _, tenant := range tenants {
		tree = append(tree, vo.SysTenantTreeSelect(tenant))
	}
	return tree
}

// parseDataToTree 将数据解析为树结构，构建前端所需要下拉树结构
func (r *SysTenantImpl) parseDataToTree(sysTenants []model.SysTenant) []model.SysTenant {
	// 节点分组
	nodesMap := make(map[string][]model.SysTenant)
	// 节点id
	treeIds := []string{}
	// 树节点
	tree := []model.SysTenant{}

	for _, item := range sysTenants {
		parentID := item.ParentID
		// 分组
		mapItem, ok := nodesMap[parentID]
		if !ok {
			mapItem = []model.SysTenant{}
		}
		mapItem = append(mapItem, item)
		nodesMap[parentID] = mapItem
		// 记录节点ID
		treeIds = append(treeIds, item.TenantID)
	}

	for key, value := range nodesMap {
		// 选择不是节点ID的作为树节点
		found := false
		for _, id := range treeIds {
			if id == key {
				found = true
				break
			}
		}
		if !found {
			tree = append(tree, value...)
		}
	}

	for i, node := range tree {
		iN := r.parseDataToTreeComponet(node, &nodesMap)
		tree[i] = iN
	}

	return tree
}

// parseDataToTreeComponet 递归函数处理子节点
func (r *SysTenantImpl) parseDataToTreeComponet(node model.SysTenant, nodesMap *map[string][]model.SysTenant) model.SysTenant {
	id := node.TenantID
	children, ok := (*nodesMap)[id]
	if ok {
		node.Children = children
	}
	if len(node.Children) > 0 {
		for i, child := range node.Children {
			icN := r.parseDataToTreeComponet(child, nodesMap)
			node.Children[i] = icN
		}
	}
	return node
}

// UpdateUDMSubTenantID 更新签约用户租户信息
func (r *SysTenantImpl) UpdateUDMSubTenantID(tenantId, assetKey string) int64 {
	return r.sysTenantRepository.UpdateUDMSubTenantID(tenantId, assetKey)
}
