package com.njcn.rdms.module.system.service.user;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.common.annotations.VisibleForTesting;
import com.njcn.rdms.framework.common.enums.CommonStatusEnum;
import com.njcn.rdms.framework.common.exception.ServiceException;
import com.njcn.rdms.framework.common.util.object.BeanUtils;
import com.njcn.rdms.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.njcn.rdms.framework.security.core.util.SecurityFrameworkUtils;
import com.njcn.rdms.module.system.controller.admin.user.vo.userManagementRelation.MySubordinateTreeRespVO;
import com.njcn.rdms.module.system.controller.admin.user.vo.userManagementRelation.UserManagementRelationQueryReqVO;
import com.njcn.rdms.module.system.controller.admin.user.vo.userManagementRelation.UserManagementRelationSaveReqVO;
import com.njcn.rdms.module.system.controller.admin.user.vo.userManagementRelation.UserManagementRelationTreeRespVO;
import com.njcn.rdms.module.system.dal.dataobject.user.AdminUserDO;
import com.njcn.rdms.module.system.dal.dataobject.user.UserManagementRelationDO;
import com.njcn.rdms.module.system.dal.mysql.user.AdminUserMapper;
import com.njcn.rdms.module.system.dal.mysql.user.UserManagementRelationMapper;
import jakarta.annotation.Resource;
import lombok.Data;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static com.njcn.rdms.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.njcn.rdms.module.system.enums.ErrorCodeConstants.USER_MANAGEMENT_RELATION_MANAGER_EXISTS;
import static com.njcn.rdms.module.system.enums.ErrorCodeConstants.USER_MANAGEMENT_RELATION_NOT_FOUND;

/**
 * 用户管理链路 Service 实现类
 * 提供用户管理链路的增删改查功能，以及树形结构构建功能
 * 树形结构用于前端展示用户的上下级层级关系
 * 业务规则：
 * 1. 一个用户只能有一个直属上级
 * 2. 一个用户可以有多个下属
 * 3. 可以将自己设置为被管理者（自己管理自己）
 *
 * @author dklive
 */
@Service
@Validated
public class UserManagementRelationServiceImpl implements UserManagementRelationService {

    @Resource
    private UserManagementRelationMapper userManagementRelationMapper;

    @Resource
    private AdminUserMapper adminUserMapper;

    @Resource
    private AdminUserService adminUserService;

    /**
     * 树形结构构建上下文
     * 包含构建树形结构所需的所有基础数据
     */
    @Data
    private static class TreeBuildContext {
        private Map<Long, AdminUserDO> userMap;
        private Map<Long, List<Long>> managerToSubordinatesMap;
        private Map<Long, UserManagementRelationDO> subordinateToRelationMap;
        private Set<Long> hasManagerUserIds;
        private Set<Long> allUserIds;
    }

    /**
     * 创建用户管理链路
     * 业务逻辑：
     * 1. 校验被管理者是否已有直属上级（一个用户只能有一个直属上级）
     * 2. 插入关系记录
     *
     * @param createReqVO 创建请求VO
     * @return 关系记录主键ID
     */
    @Override
    public Long createRelation(UserManagementRelationSaveReqVO createReqVO) {
        validateRelationForCreateOrUpdate(null, createReqVO.getSubordinateUserId());
        UserManagementRelationDO relation = BeanUtils.toBean(createReqVO, UserManagementRelationDO.class);
        userManagementRelationMapper.insert(relation);
        return relation.getId();
    }

    /**
     * 更新用户管理链路
     * 业务逻辑：
     * 1. 校验关系记录是否存在
     * 2. 校验被管理者是否已有其他直属上级（一个用户只能有一个直属上级）
     * 3. 更新关系记录
     *
     * @param updateReqVO 更新请求VO
     */
    @Override
    public void updateRelation(UserManagementRelationSaveReqVO updateReqVO) {
        validateRelationForCreateOrUpdate(updateReqVO.getId(), updateReqVO.getSubordinateUserId());
        UserManagementRelationDO updateObj = BeanUtils.toBean(updateReqVO, UserManagementRelationDO.class);
        userManagementRelationMapper.updateById(updateObj);
    }

    /**
     * 删除用户管理链路
     * 业务逻辑：
     * 1. 校验关系记录是否存在
     * 2. 根据主键ID删除关系记录
     *
     * @param id 关系记录主键ID
     */
    @Override
    public void deleteRelation(Long id) {
        validateRelationExists(id);
        userManagementRelationMapper.deleteById(id);
    }

    /**
     * 批量删除用户管理链路
     * 业务逻辑：
     * 根据主键ID列表批量删除关系记录
     *
     * @param ids 关系记录主键ID列表
     */
    @Override
    public void deleteRelationList(List<Long> ids) {
        if (CollUtil.isEmpty(ids)) {
            return;
        }
        userManagementRelationMapper.deleteByIds(ids);
    }

    /**
     * 校验关系记录的合法性
     * 校验规则：
     * 1. 更新时，校验关系记录是否存在
     * 2. 被管理者用户只能有一个直属上级（创建时校验，更新时校验是否更换了被管理者）
     *
     * @param id                关系记录主键ID（创建时为null）
     * @param subordinateUserId 被管理者用户ID
     */
    private void validateRelationForCreateOrUpdate(Long id, Long subordinateUserId) {
        validateRelationExists(id);
        validateSubordinateHasNoOtherManager(id, subordinateUserId);
    }

    /**
     * 校验被管理者是否已有其他直属上级
     * 业务规则：一个用户只能有一个直属上级
     * 校验逻辑：
     * 1. 查询该被管理者用户的所有关系记录
     * 2. 如果存在其他关系记录（排除当前记录），则抛出异常
     *
     * @param excludeId         排除的关系记录主键ID（创建时为null，更新时为当前记录ID）
     * @param subordinateUserId 被管理者用户ID
     * @throws ServiceException 被管理者已有其他直属上级时抛出异常
     */
    private void validateSubordinateHasNoOtherManager(Long excludeId, Long subordinateUserId) {
        if (subordinateUserId == null) {
            return;
        }
        List<UserManagementRelationDO> existingRelations =
                userManagementRelationMapper.selectListBySubordinateUserId(subordinateUserId);
        if (CollUtil.isEmpty(existingRelations)) {
            return;
        }
        if (excludeId == null) {
            throw exception(USER_MANAGEMENT_RELATION_MANAGER_EXISTS);
        }
        boolean hasOtherManager = existingRelations.stream()
                .anyMatch(relation -> !relation.getId().equals(excludeId));
        if (hasOtherManager) {
            throw exception(USER_MANAGEMENT_RELATION_MANAGER_EXISTS);
        }
    }

    /**
     * 校验关系记录是否存在
     *
     * @param id 关系记录主键ID
     * @throws ServiceException 关系记录不存在时抛出异常
     */
    @VisibleForTesting
    void validateRelationExists(Long id) {
        if (id == null) {
            return;
        }
        if (userManagementRelationMapper.selectById(id) == null) {
            throw exception(USER_MANAGEMENT_RELATION_NOT_FOUND);
        }
    }

    /**
     * 根据主键ID获取用户管理链路
     *
     * @param id 关系记录主键ID
     * @return 用户管理链路DO
     */
    @Override
    public UserManagementRelationDO getRelation(Long id) {
        return userManagementRelationMapper.selectOne(
                buildValidQuery().eq(UserManagementRelationDO::getId, id)
        );
    }

    /**
     * 根据主键ID列表获取用户管理链路列表
     *
     * @param ids 关系记录主键ID列表
     * @return 用户管理链路DO列表
     */
    @Override
    public List<UserManagementRelationDO> getRelationList(Collection<Long> ids) {
        if (CollUtil.isEmpty(ids)) {
            return Collections.emptyList();
        }
        return userManagementRelationMapper.selectList(
                buildValidQuery().in(UserManagementRelationDO::getId, ids)
        );
    }

    /**
     * 根据查询条件获取用户管理链路树形结构
     * 业务逻辑：
     * 1. 构建树形结构上下文（包含所有基础数据）
     * 2. 根据查询条件确定目标用户ID（subordinateUserId优先于managerUserId）
     * 3. 如果有目标用户，只构建包含该用户的分支（上级链 + 下级树）
     * 4. 如果没有目标用户，返回完整的树形结构
     * <p>
     * 查询参数优先级：
     * - 当subordinateUserId和managerUserId同时存在时，优先使用subordinateUserId
     * - 正常业务场景下，两个参数只会传递其中一个
     * <p>
     * 边界情况处理：
     * - 两个参数都为null：返回完整的树形结构（等同于getRelationTree）
     * - subordinateUserId不为null：构建包含该用户的上级链和下级树，不包含同级节点
     * - managerUserId不为null：构建以该用户为根节点的完整下级树
     *
     * @param reqVO 查询条件VO，包含subordinateUserId或managerUserId
     * @return 用户管理链路树形结构列表
     */
    @Override
    public List<UserManagementRelationTreeRespVO> getRelationQuery(UserManagementRelationQueryReqVO reqVO) {
        TreeBuildContext context = buildTreeContext(reqVO);
        if (context == null) {
            return Collections.emptyList();
        }

        Long targetUserId = determineTargetUserId(reqVO, context);
        if (targetUserId == null) {
            return Collections.emptyList();
        }

        return buildTargetBranchTree(targetUserId, context);
    }

    /**
     * 根据管理者用户ID获取其下属关系列表
     *
     * @param managerUserId 管理者用户ID
     * @return 用户管理链路DO列表
     */
    @Override
    public List<UserManagementRelationDO> getRelationListByManagerUserId(Long managerUserId) {
        return userManagementRelationMapper.selectListByManagerUserId(managerUserId);
    }

    /**
     * 根据被管理者用户ID获取其上级关系列表
     * 注意：由于一个用户只能有一个直属上级，此方法最多返回一条记录
     *
     * @param subordinateUserId 被管理者用户ID
     * @return 用户管理链路DO列表
     */
    @Override
    public List<UserManagementRelationDO> getRelationListBySubordinateUserId(Long subordinateUserId) {
        if (subordinateUserId == null) {
            return Collections.emptyList();
        }
        return userManagementRelationMapper.selectValidListBySubordinateUserId(subordinateUserId);
    }

    /**
     * 获得某用户当前生效的直属上级
     *
     * @param userId 用户ID
     * @return 直属上级用户，不存在则返回 null
     */
    @Override
    public AdminUserDO getDirectManager(Long userId) {
        List<UserManagementRelationDO> relations = getRelationListBySubordinateUserId(userId);
        if (CollUtil.isEmpty(relations)) {
            return null;
        }
        Long managerUserId = relations.get(0).getManagerUserId();
        if (managerUserId == null) {
            return null;
        }
        AdminUserDO manager = adminUserService.getUser(managerUserId);
        if (!adminUserService.isUserAvailable(manager)) {
            return null;
        }
        return manager;
    }

    /**
     * 获取候选的下属用户列表
     * @return 候选的下属用户列表
     */
    @Override
    public List<AdminUserDO> getCandidateSubordinateUsers() {
        List<AdminUserDO> users = adminUserService.getUserListByStatus(CommonStatusEnum.ENABLE.getStatus());
        if (CollUtil.isEmpty(users)) {
            return Collections.emptyList();
        }

        List<UserManagementRelationDO> relations =
                userManagementRelationMapper.selectList(new UserManagementRelationQueryReqVO());
        Set<Long> boundSubordinateUserIds = relations.stream()
                .map(UserManagementRelationDO::getSubordinateUserId)
                .collect(Collectors.toSet());

        return users.stream()
                .filter(adminUserService::isUserAvailable)
                .filter(user -> !boundSubordinateUserIds.contains(user.getId()))
                .sorted(Comparator.comparing(AdminUserDO::getDeptId, Comparator.nullsLast(Long::compareTo))
                        .thenComparing(AdminUserDO::getNickname, Comparator.nullsLast(String::compareTo))
                        .thenComparing(AdminUserDO::getId))
                .collect(Collectors.toList());
    }

    /**
     * 获取用户管理链路树形结构
     * 业务逻辑：
     * 1. 构建树形结构上下文（包含所有基础数据）
     * 2. 找出所有根节点（没有上级的用户，即最高领导；也包括自己管理自己的用户）
     * 3. 从根节点开始递归构建完整的树形结构
     * <p>
     * 边界情况处理：
     * - 根节点（还没有设置直属上级的用户）：managerUserId设置为自己的userId，managerNickname为自己的昵称
     * - 自己管理自己的用户：managerUserId等于userId，managerNickname为自己的昵称
     * - 基层员工：没有下级，children为空列表
     * - 空数据：返回空列表
     *
     * @return 用户管理链路树形结构列表
     */
    @Override
    public List<UserManagementRelationTreeRespVO> getRelationTree(UserManagementRelationQueryReqVO reqVO) {
        TreeBuildContext context = buildTreeContext(reqVO);
        if (context == null) {
            return Collections.emptyList();
        }
        return buildFullTree(context);
    }

    @Override
    public MySubordinateTreeRespVO getMySubordinateTree(Long rootUserId) {
        Long resolvedRootUserId = rootUserId != null ? rootUserId : SecurityFrameworkUtils.getLoginUserId();
        if (resolvedRootUserId == null) {
            return null;
        }
        TreeBuildContext context = buildTreeContext(new UserManagementRelationQueryReqVO());
        if (context == null) {
            AdminUserDO self = adminUserService.getUser(resolvedRootUserId);
            if (!adminUserService.isUserAvailable(self)) {
                return null;
            }
            MySubordinateTreeRespVO root = new MySubordinateTreeRespVO();
            root.setUserId(self.getId());
            root.setUserNickname(self.getNickname());
            root.setIsRoot(Boolean.TRUE);
            root.setSubordinateCount(0);
            root.setChildren(Collections.emptyList());
            return root;
        }
        return buildMySubordinateTreeNode(resolvedRootUserId, true, context);
    }

    @Override
    public Set<Long> getAllSubordinateUserIds(Long managerUserId) {
        if (managerUserId == null) {
            return Collections.emptySet();
        }
        TreeBuildContext context = buildTreeContext(new UserManagementRelationQueryReqVO());
        if (context == null) {
            return Collections.emptySet();
        }
        Set<Long> result = new LinkedHashSet<>();
        collectSubordinateIds(managerUserId, context, result);
        result.remove(managerUserId);
        return result;
    }

    /**
     * 通过某个用户的id，判断管理链路表中是否有该用户的记录
     * 判断原则：
     * --管理者ID或被管理者ID有一个字段的值等于用户id，且该记录没有被逻辑删除
     * --则认为管理链路表中还在使用该用户
     *
     * @param userId 用户id
     * @return true:有该用户的记录，false:没有该用户的记录
     */
    @Override
    public Boolean hasRelation(Long userId) {
        if (userId == null) {
            return false;
        }
        LambdaQueryWrapperX<UserManagementRelationDO> wrapper = new LambdaQueryWrapperX<>();
        wrapper.eq(UserManagementRelationDO::getManagerUserId, userId)
                .or()
                .eq(UserManagementRelationDO::getSubordinateUserId, userId);
        return userManagementRelationMapper.selectCount(wrapper) > 0;
    }

    /**
     * 构建树形结构上下文
     * 查询并组装构建树形结构所需的所有基础数据
     *
     * @param reqVO 查询条件VO，包含fromUserIndex和deptId
     * @return 树形结构上下文，如果没有数据则返回null
     */
    private TreeBuildContext buildTreeContext(UserManagementRelationQueryReqVO reqVO) {
        List<UserManagementRelationDO> allRelations = userManagementRelationMapper.selectList(new UserManagementRelationQueryReqVO());
        if (CollUtil.isEmpty(allRelations)) {
            return null;
        }

        if (Boolean.TRUE.equals(reqVO.getFromUserIndex()) && reqVO.getDeptId() != null && reqVO.getDeptId() != 100L) {
            List<AdminUserDO> deptUsers = adminUserService.getAllUserByDeptId(reqVO.getDeptId());
            Set<Long> deptUserIds = deptUsers.stream().map(AdminUserDO::getId).collect(Collectors.toSet());
            allRelations = allRelations.stream()
                    .filter(relation -> deptUserIds.contains(relation.getManagerUserId())
                            && deptUserIds.contains(relation.getSubordinateUserId()))
                    .collect(Collectors.toList());
            if (CollUtil.isEmpty(allRelations)) {
                return null;
            }
        }

        Set<Long> allUserIds = new HashSet<>();
        for (UserManagementRelationDO relation : allRelations) {
            allUserIds.add(relation.getManagerUserId());
            allUserIds.add(relation.getSubordinateUserId());
        }

        List<AdminUserDO> users = adminUserMapper.selectByIds(allUserIds);
        Map<Long, AdminUserDO> userMap = users.stream()
                .collect(Collectors.toMap(AdminUserDO::getId, user -> user));

        Map<Long, List<Long>> managerToSubordinatesMap = allRelations.stream()
                .collect(Collectors.groupingBy(
                        UserManagementRelationDO::getManagerUserId,
                        Collectors.mapping(UserManagementRelationDO::getSubordinateUserId, Collectors.toList())
                ));

        Map<Long, UserManagementRelationDO> subordinateToRelationMap = allRelations.stream()
                .collect(Collectors.toMap(
                        UserManagementRelationDO::getSubordinateUserId,
                        relation -> relation,
                        (existing, replacement) -> existing
                ));

        Set<Long> hasManagerUserIds = allRelations.stream()
                .filter(relation -> !relation.getManagerUserId().equals(relation.getSubordinateUserId()))
                .map(UserManagementRelationDO::getSubordinateUserId)
                .collect(Collectors.toSet());

        TreeBuildContext context = new TreeBuildContext();
        context.setUserMap(userMap);
        context.setManagerToSubordinatesMap(managerToSubordinatesMap);
        context.setSubordinateToRelationMap(subordinateToRelationMap);
        context.setHasManagerUserIds(hasManagerUserIds);
        context.setAllUserIds(allUserIds);
        return context;
    }

    /**
     * 构建完整的树形结构
     * 从所有根节点开始构建完整的树形结构
     *
     * @param context 树形结构上下文
     * @return 完整的树形结构列表
     */
    private List<UserManagementRelationTreeRespVO> buildFullTree(TreeBuildContext context) {
        List<Long> rootUserIds = context.getAllUserIds().stream()
                .filter(userId -> !context.getHasManagerUserIds().contains(userId))
                .toList();

        List<UserManagementRelationTreeRespVO> treeList = new ArrayList<>();
        for (Long rootUserId : rootUserIds) {
            UserManagementRelationTreeRespVO rootNode = buildRootNode(rootUserId, context);
            if (rootNode != null) {
                treeList.add(rootNode);
            }
        }
        return treeList;
    }

    /**
     * 构建目标用户相关的分支树形结构（搜索模式）
     * 只包含目标用户的上级链和目标用户本身，不显示下级
     * <p>
     * 构建逻辑：
     * 1. 从目标用户向上追溯到根节点，记录上级链
     * 2. 从根节点开始，只沿着包含目标用户的分支向下构建
     * 3. 目标用户节点不构建下级
     *
     * @param targetUserId 目标用户ID
     * @param context      树形结构上下文
     * @return 目标用户相关的分支树形结构列表
     */
    private List<UserManagementRelationTreeRespVO> buildTargetBranchTree(Long targetUserId, TreeBuildContext context) {
        AdminUserDO targetUser = context.getUserMap().get(targetUserId);
        if (targetUser == null) {
            return Collections.emptyList();
        }

        UserManagementRelationDO targetRelation = context.getSubordinateToRelationMap().get(targetUserId);
        Long targetRelationId = targetRelation != null ? targetRelation.getId() : null;
        if (targetRelation == null || Objects.equals(targetRelation.getManagerUserId(), targetUserId)) {
            // 根节点搜索时只返回本人，不继续展示更高层级
            UserManagementRelationTreeRespVO targetNode =
                    buildTreeNodeForSearch(targetRelationId, targetUserId, targetUserId, context);
            return targetNode == null ? Collections.emptyList() : Collections.singletonList(targetNode);
        }

        Long managerUserId = targetRelation.getManagerUserId();
        UserManagementRelationDO managerRelation = context.getSubordinateToRelationMap().get(managerUserId);
        Long managerRelationId = managerRelation != null ? managerRelation.getId() : null;
        UserManagementRelationTreeRespVO managerNode =
                buildTreeNodeForSearch(managerRelationId, managerUserId, managerUserId, context);
        if (managerNode == null) {
            return Collections.emptyList();
        }

        UserManagementRelationTreeRespVO targetNode =
                buildTreeNodeForSearch(targetRelationId, targetUserId, managerUserId, context);
        if (targetNode == null) {
            return Collections.emptyList();
        }

        managerNode.setChildren(Collections.singletonList(targetNode));
        return Collections.singletonList(managerNode);
    }

    /**
     * 构建根节点
     *
     * @param rootUserId 根节点用户ID
     * @param context    树形结构上下文
     * @return 根节点
     */
    private UserManagementRelationTreeRespVO buildRootNode(Long rootUserId, TreeBuildContext context) {
        UserManagementRelationDO rootRelation = context.getSubordinateToRelationMap().get(rootUserId);
        Long rootRelationId = rootRelation != null ? rootRelation.getId() : null;
        Long rootManagerUserId;
        if (rootRelation == null) {
            rootManagerUserId = rootUserId;
        } else if (rootRelation.getManagerUserId().equals(rootRelation.getSubordinateUserId())) {
            rootManagerUserId = rootUserId;
        } else {
            rootManagerUserId = rootRelation.getManagerUserId();
        }
        return buildTreeNode(rootRelationId, rootUserId, rootManagerUserId, context);
    }

    /**
     * 确定目标用户ID
     * 根据查询参数优先级确定目标用户：
     * 1. 如果subordinateUserId不为null，返回subordinateUserId
     * 2. 如果managerUserId不为null，返回managerUserId
     * 3. 否则返回null（表示查询所有）
     *
     * @param reqVO   查询条件VO
     * @param context 树形结构上下文
     * @return 目标用户ID，如果没有指定则返回null
     */
    private Long determineTargetUserId(UserManagementRelationQueryReqVO reqVO, TreeBuildContext context) {
        if (reqVO == null) {
            return null;
        }
        if (reqVO.getSubordinateUserId() != null && context.getAllUserIds().contains(reqVO.getSubordinateUserId())) {
            return reqVO.getSubordinateUserId();
        }
        if (reqVO.getManagerUserId() != null && context.getAllUserIds().contains(reqVO.getManagerUserId())) {
            return reqVO.getManagerUserId();
        }
        return null;
    }

    /**
     * 构建树形节点
     * 构建逻辑：
     * 1. 根据用户ID获取用户信息
     * 2. 设置节点的基本信息（关系记录ID、用户ID、用户昵称）
     * 3. 设置上级信息（上级用户ID、上级用户昵称）
     * 4. 递归构建所有下级节点列表
     *
     * @param relationId    关系记录主键ID（根节点且非自己管理自己时为null）
     * @param userId        当前用户ID
     * @param managerUserId 上级用户ID（根节点时为自己的userId）
     * @param context       树形结构上下文
     * @return 树形节点
     */
    private UserManagementRelationTreeRespVO buildTreeNode(Long relationId, Long userId, Long managerUserId,
                                                           TreeBuildContext context) {
        AdminUserDO user = context.getUserMap().get(userId);
        if (user == null) {
            return null;
        }

        UserManagementRelationTreeRespVO node = new UserManagementRelationTreeRespVO();
        node.setId(relationId);
        node.setUserId(userId);
        node.setUserNickname(user.getNickname());
        node.setManagerUserId(managerUserId);

        if (managerUserId != null) {
            AdminUserDO managerUser = context.getUserMap().get(managerUserId);
            if (managerUser != null) {
                node.setManagerNickname(managerUser.getNickname());
            }
        }

        List<Long> subordinateIds = context.getManagerToSubordinatesMap().get(userId);
        if (CollUtil.isNotEmpty(subordinateIds)) {
            List<UserManagementRelationTreeRespVO> children = new ArrayList<>();
            for (Long subordinateId : subordinateIds) {
                if (subordinateId.equals(userId)) {
                    continue;
                }
                UserManagementRelationDO childRelation = context.getSubordinateToRelationMap().get(subordinateId);
                Long childRelationId = childRelation != null ? childRelation.getId() : null;
                UserManagementRelationTreeRespVO childNode = buildTreeNode(childRelationId, subordinateId, userId, context);
                if (childNode != null) {
                    children.add(childNode);
                }
            }
            node.setChildren(children);
        } else {
            node.setChildren(Collections.emptyList());
        }

        return node;
    }

    /**
     * 构建树形节点（搜索模式）
     * 与buildTreeNode的区别：不构建下级节点，只返回当前节点信息
     *
     * @param relationId    关系记录主键ID
     * @param userId        当前用户ID
     * @param managerUserId 上级用户ID
     * @param context       树形结构上下文
     * @return 树形节点（无下级）
     */
    private UserManagementRelationTreeRespVO buildTreeNodeForSearch(Long relationId, Long userId, Long managerUserId,
                                                                     TreeBuildContext context) {
        AdminUserDO user = context.getUserMap().get(userId);
        if (user == null) {
            return null;
        }

        UserManagementRelationTreeRespVO node = new UserManagementRelationTreeRespVO();
        node.setId(relationId);
        node.setUserId(userId);
        node.setUserNickname(user.getNickname());
        node.setManagerUserId(managerUserId);

        if (managerUserId != null) {
            AdminUserDO managerUser = context.getUserMap().get(managerUserId);
            if (managerUser != null) {
                node.setManagerNickname(managerUser.getNickname());
            }
        }

        node.setChildren(Collections.emptyList());
        return node;
    }

    private MySubordinateTreeRespVO buildMySubordinateTreeNode(Long userId, boolean root, TreeBuildContext context) {
        AdminUserDO user = context.getUserMap().get(userId);
        if (!adminUserService.isUserAvailable(user)) {
            return null;
        }
        List<MySubordinateTreeRespVO> children = new ArrayList<>();
        for (Long subordinateId : context.getManagerToSubordinatesMap().getOrDefault(userId, Collections.emptyList())) {
            if (Objects.equals(subordinateId, userId)) {
                continue;
            }
            MySubordinateTreeRespVO child = buildMySubordinateTreeNode(subordinateId, false, context);
            if (child != null) {
                children.add(child);
            }
        }
        MySubordinateTreeRespVO node = new MySubordinateTreeRespVO();
        node.setUserId(user.getId());
        node.setUserNickname(user.getNickname());
        node.setIsRoot(root);
        node.setChildren(children);
        node.setSubordinateCount(sumSubordinateCount(children));
        return node;
    }

    private int sumSubordinateCount(List<MySubordinateTreeRespVO> children) {
        int total = 0;
        for (MySubordinateTreeRespVO child : children) {
            if (child == null) {
                continue;
            }
            total += 1;
            total += child.getSubordinateCount() == null ? 0 : child.getSubordinateCount();
        }
        return total;
    }

    private void collectSubordinateIds(Long managerUserId, TreeBuildContext context, Set<Long> result) {
        for (Long subordinateId : context.getManagerToSubordinatesMap().getOrDefault(managerUserId, Collections.emptyList())) {
            if (Objects.equals(subordinateId, managerUserId)) {
                continue;
            }
            AdminUserDO subordinate = context.getUserMap().get(subordinateId);
            if (!adminUserService.isUserAvailable(subordinate)) {
                continue;
            }
            if (result.add(subordinateId)) {
                collectSubordinateIds(subordinateId, context, result);
            }
        }
    }

    /**
     * 统一时间有效性过滤条件：
     * <p>
     * 1.如果这两个字段都是null，那就直接查出来
     * 2.如果effective_util是null、effective_from不是null，那就只需要当前时间>=effective_from就行
     * 3.如果effective_from是null、effective_util不是null，那就只需要当前时间<=effective_util就行
     * <p>
     * 如果上面三个条件都不满足，那就判断为此条关系已经失效，不查出来
     */
    private LambdaQueryWrapper<UserManagementRelationDO> buildValidQuery() {
        LocalDateTime now = LocalDateTime.now();
        return new LambdaQueryWrapper<UserManagementRelationDO>()
                // (from IS NULL OR from <= now)
                .and(w -> w.isNull(UserManagementRelationDO::getEffectiveFrom)
                        .or().le(UserManagementRelationDO::getEffectiveFrom, now))
                // (until IS NULL OR until >= now)
                .and(w -> w.isNull(UserManagementRelationDO::getEffectiveUntil)
                        .or().ge(UserManagementRelationDO::getEffectiveUntil, now));
        // BaseMapperX 通常已自动处理 deleted 字段，无需额外加
    }

}
