package com.engine.organization.entity.company.bo;

import com.engine.organization.entity.company.dto.CompListDTO;
import com.engine.organization.entity.company.param.CompParam;
import com.engine.organization.entity.company.po.CompPO;
import com.engine.organization.entity.searchtree.SearchTree;
import com.engine.organization.mapper.comp.CompMapper;
import com.engine.organization.util.db.MapperProxyFactory;
import org.apache.commons.collections.CollectionUtils;
import weaver.general.Util;

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

/**
 * @author:dxfeng
 * @createTime: 2022/11/24
 * @version: 1.0
 */
public class CompBO {

    private static CompMapper getCompMapper() {
        return MapperProxyFactory.getProxy(CompMapper.class);
    }

    public static List<SearchTree> buildSetToSearchTree(Set<CompPO> comps) {
        return comps.stream().sorted(Comparator.comparing(item -> null == item.getShowOrder() ? 0 : item.getShowOrder())).map(item -> {
            SearchTree tree = new SearchTree();
            tree.setCanClick(true);
            tree.setCanceled(item.getCanceled() != null && item.getCanceled() != 0);
            tree.setIcon("icon-coms-LargeArea");
            tree.setId(item.getId().toString());
            tree.setIsParent(false);
            tree.setIsVirtual("0");
            tree.setName(item.getSubCompanyName());
            tree.setPid(item.getSupSubComId().toString());
            tree.setSelected(false);
            tree.setType("1");
            tree.setOrderNum(null == item.getShowOrder() ? 0 : item.getShowOrder());
            return tree;
        }).collect(Collectors.toList());
    }

    /**
     * 搜索条件转换实体对象
     *
     * @param param
     * @param userId
     * @return
     */
    public static CompPO convertParamToPO(CompParam param, Integer userId) {
        if (null == param) {
            return null;
        }
        return CompPO
                .builder()
                .id(param.getId() == null ? 0 : param.getId())
                .subCompanyName(param.getSubCompanyName())
                .subCompanyDesc(param.getSubCompanyDesc())
                // 所属集团默认为1
                .companyId(null == param.getCompanyId() ? 1 : param.getCompanyId())
                .supSubComId(param.getSupSubComId())
                .url(param.getUrl())
                .canceled(param.getCanceled() == null ? null : param.getCanceled() ? 0 : 1)
                .subCompanyCode(param.getSubCompanyCode())
                .outKey(param.getOutKey())
                .limitUsers(null == param.getLimitUsers() ? 0 : param.getLimitUsers())
                .uuid(param.getUuid())
                .showOrder(param.getShowOrder())
                .showOrderOfTree(param.getShowOrderOfTree())
                .created(new Date())
                .creater(userId)
                .modified(new Date())
                .modifier(userId)
                .build();
    }

    public static List<CompListDTO> buildCompDTOList(Collection<CompPO> list, List<CompPO> filterList) {
        // 搜索结果为空，直接返回空
        if (CollectionUtils.isEmpty(filterList)) {
            return Collections.emptyList();
        }
        // 递归添加父级数据
        Map<Integer, CompPO> poMaps = list.stream().collect(Collectors.toMap(CompPO::getId, item -> item));
        List<CompPO> addedList = new ArrayList<>();
        for (CompPO po : filterList) {
            dealParentData(addedList, po, poMaps);
        }

        return buildCompDTOList(addedList);
    }

    public static List<CompListDTO> buildCompDTOList(List<CompPO> list) {

        Map<Integer, CompPO> poMaps = list.stream().collect(Collectors.toMap(CompPO::getId, item -> item));

        List<CompListDTO> dtoList = list.stream().map(e ->
                CompListDTO
                        .builder()
                        .id(e.getId())
                        .subCompanyCode(e.getSubCompanyCode())
                        .subCompanyDesc(e.getSubCompanyDesc())
                        .subCompanyName(e.getSubCompanyName())
                        .supSubComId(e.getSupSubComId())
                        .supSubComName(null == poMaps.get(e.getSupSubComId()) ? "" : poMaps.get(e.getSupSubComId()).getSubCompanyName())
                        .showOrder(e.getShowOrder())
                        .canceled(null == e.getCanceled() ? 0 : e.getCanceled())
                        .build()).collect(Collectors.toList());
        Map<Integer, List<CompListDTO>> collects = dtoList.stream().filter(item -> 0 != item.getSupSubComId()).collect(Collectors.groupingBy(CompListDTO::getSupSubComId));
        // 处理被引用数据
        List<String> usedIds = getCompMapper().listUsedId();
        // 兼容MySQL
        List<String> strings = getCompMapper().listUsedIds();
        if (CollectionUtils.isNotEmpty(strings)) {
            usedIds.addAll(strings);
        }
        List<String> collect = Arrays.stream(String.join(",", usedIds).split(",")).collect(Collectors.toList());
        Set<Integer> leafs = new HashSet<>();
        List<CompListDTO> collectTree = dtoList.stream().peek(e -> {
            List<CompListDTO> childList = collects.get(e.getId());
            leafs.add(e.getId());
            if (CollectionUtils.isNotEmpty(childList)) {
                e.setChildren(childList);
                e.setIsUsed(1);
            } else {
                if (collect.contains(Util.null2String(e.getId()))) {
                    e.setIsUsed(1);
                } else {
                    e.setIsUsed(0);
                }
            }
        }).collect(Collectors.toList());
        return collectTree.stream().filter(item -> !leafs.contains(item.getSupSubComId())).collect(Collectors.toList());
    }

    /**
     * 递归获取查询后数据的父级数据
     *
     * @param addedList
     * @param po
     * @param poMaps
     */
    private static void dealParentData(List<CompPO> addedList, CompPO po, Map<Integer, CompPO> poMaps) {
        if (!addedList.contains(po)) {
            addedList.add(po);
        }
        CompPO parentCompPO = poMaps.get(po.getSupSubComId());
        if (null != parentCompPO) {
            dealParentData(addedList, parentCompPO, poMaps);
        }
    }
}
