package com.sundot.airport.system.service.impl;

import com.sundot.airport.common.core.domain.TreeQuery;
import com.sundot.airport.common.core.domain.TreeSelect;
import com.sundot.airport.common.enums.TreeTypes;
import com.sundot.airport.common.utils.StringUtils;
import com.sundot.airport.system.domain.BaseCheckCategory;
import com.sundot.airport.system.domain.BaseCheckPoint;
import com.sundot.airport.system.domain.BasePosition;
import com.sundot.airport.system.domain.BaseSeizeCategory;
import com.sundot.airport.system.mapper.*;
import com.sundot.airport.system.service.ISysTreeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 树结构通用构建服务
 */
@Service
public class SysTreeServiceImpl implements ISysTreeService {

    @Autowired
    private BaseSeizeCategoryMapper categoryMapper;

    @Autowired
    private BasePositionMapper positionMapper;

    @Autowired
    private BaseCheckPointMapper checkPointMapper;

    @Autowired
    private BaseCheckCategoryMapper checkCategoryMapper;

    /**
     * 查询树结构信息
     *
     * @param treeQuery 查询参数
     * @return 树信息集合
     */
    @Override
    public List<TreeSelect> selectTreeList(TreeQuery treeQuery) {
        if (TreeTypes.ITEM_CATEGORY.getCode().equals(treeQuery.getTreeType())) {
            BaseSeizeCategory baseSeizeCategory = new BaseSeizeCategory();
            if (StringUtils.isNotEmpty(treeQuery.getLabel())) {
                baseSeizeCategory.setName(treeQuery.getLabel());
            }
            List<BaseSeizeCategory> list = categoryMapper.selectBaseSeizeCategoryList(baseSeizeCategory);
            return buildGenericTree(list,
                    BaseSeizeCategory::getCode,
                    BaseSeizeCategory::getId,
                    BaseSeizeCategory::getParentId,
                    BaseSeizeCategory::getName,
                    0L,
                    treeQuery.getMaxLevel());
        } else if (TreeTypes.POSITION.getCode().equals(treeQuery.getTreeType())) {
            BasePosition basePosition = new BasePosition();
            if (StringUtils.isNotEmpty(treeQuery.getLabel())) {
                basePosition.setName(treeQuery.getLabel());
            }
            List<BasePosition> list = positionMapper.selectBasePositionList(basePosition);
            return buildGenericTree(list,
                    BasePosition::getCode,
                    BasePosition::getId,
                    BasePosition::getParentId,
                    BasePosition::getName,
                    0L,
                    treeQuery.getMaxLevel());
        }else if (TreeTypes.CHECK_POINT.getCode().equals(treeQuery.getTreeType())){
            BaseCheckPoint baseCheckPoint = new BaseCheckPoint();
            if (StringUtils.isNotEmpty(treeQuery.getLabel())) {
                baseCheckPoint.setName(treeQuery.getLabel());
            }
            List<BaseCheckPoint> list = checkPointMapper.selectBaseCheckPointList(baseCheckPoint);
            return buildGenericTree(list,
                    BaseCheckPoint::getCode,
                    BaseCheckPoint::getId,
                    BaseCheckPoint::getParentId,
                    BaseCheckPoint::getName,
                    0L,
                    treeQuery.getMaxLevel());
        } else if (TreeTypes.CHECK_CATEGORY.getCode().equals(treeQuery.getTreeType())) {
            BaseCheckCategory baseCheckCategory = new BaseCheckCategory();
            if (StringUtils.isNotEmpty(treeQuery.getLabel())) {
                baseCheckCategory.setName(treeQuery.getLabel());
            }
            List<BaseCheckCategory> list = checkCategoryMapper.selectBaseCheckCategoryList(baseCheckCategory);
            return buildGenericTree(list,
                    BaseCheckCategory::getCode,
                    BaseCheckCategory::getId,
                    BaseCheckCategory::getParentId,
                    BaseCheckCategory::getName,
                    0L,
                    treeQuery.getMaxLevel());


        }
        return Collections.emptyList();
    }

    /**
     * 构建通用树结构（泛型方法）
     *
     * @param dataList       数据列表
     * @param codeGetter       获取节点code
     * @param idGetter       获取节点ID
     * @param parentIdGetter 获取父节点ID
     * @param labelGetter    获取节点标签
     * @param rootParentId   根节点的父节点ID
     * @return 树结构列表
     */
    public <T> List<TreeSelect> buildGenericTree(List<T> dataList,
                                                 Function<T, String> codeGetter,
                                                 Function<T, Long> idGetter,
                                                 Function<T, Long> parentIdGetter,
                                                 Function<T, String> labelGetter,
                                                 Long rootParentId,
                                                 Integer maxLevel) {
        if (dataList == null || dataList.isEmpty()) {
            return Collections.emptyList();
        }

        Map<Long, TreeSelect> nodeMap = new HashMap<>();
        for (T item : dataList) {
            Long id = idGetter.apply(item);
            String label = labelGetter.apply(item);
            String code = codeGetter.apply(item);
            Long parentId = parentIdGetter.apply(item);
            nodeMap.put(id, new TreeSelect(id,code, label,parentId));
        }
        Map<Long, Integer> levelMap = new HashMap<>();
        for (T item : dataList) {
            Long id = idGetter.apply(item);
            Long parentId = parentIdGetter.apply(item);
            TreeSelect node = nodeMap.get(id);

            if (parentId != null && !parentId.equals(rootParentId)) {
                TreeSelect parent = nodeMap.get(parentId);
                if (parent != null) {
                    int currentLevel = levelMap.getOrDefault(parent.getId(), 0) + 1;
                    // 如果 maxLevel 为 null 或者当前层级小于等于 maxLevel，则允许添加
                    if (maxLevel == null || currentLevel <= maxLevel) {
                        levelMap.put(id, currentLevel);
                        parent.setChildren(parent.getChildren() == null ? new ArrayList<>() : parent.getChildren());
                        parent.getChildren().add(node);
                    }
                }
            } else {
                node.setParentId(rootParentId);
                levelMap.put(id, 1); // 根节点层级为1
            }
        }

        return nodeMap.values().stream()
                .filter(n -> rootParentId.equals(n.getParentId()))
                .collect(Collectors.toList());
    }

}
