package com.bonus.material.ma.service.impl;

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

import cn.hutool.core.util.ArrayUtil;
import com.bonus.common.biz.domain.TreeSelect;
import com.bonus.common.biz.enums.DataCodeEnum;
import com.bonus.common.biz.enums.HttpCodeEnum;
import com.bonus.common.core.utils.DateUtils;
import com.bonus.common.core.utils.StringUtils;
import com.bonus.common.core.web.domain.AjaxResult;
import com.bonus.common.security.utils.SecurityUtils;
import com.bonus.material.ma.domain.TypeKeeper;
import com.bonus.material.ma.domain.TypeRepair;
import com.bonus.material.ma.service.ITypeKeeperService;
import com.bonus.material.ma.service.ITypeRepairService;
import com.bonus.material.ma.domain.vo.MaTypeConfigVo;
import com.bonus.material.ma.domain.vo.MaTypeVo;
import com.bonus.material.ma.domain.vo.MaTypeSelectVo;
import com.bonus.material.warehouse.domain.WhHouseSet;
import com.bonus.material.warehouse.service.IWhHouseSetService;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import com.bonus.material.ma.mapper.TypeMapper;
import com.bonus.material.ma.domain.Type;
import com.bonus.material.ma.service.ITypeService;

import javax.annotation.Resource;

/**
 * 物资类型管理Service业务层实现
 * @author syruan
 */
@Service
public class TypeServiceImpl implements ITypeService {

    /**
     * 物资类型管理树最小级别
     */
    public static final Integer TYPE_MIN_LEVEL = 4;

    @Resource
    private TypeMapper typeMapper;

    @Resource
    private ITypeKeeperService typeKeeperService;

    @Resource
    private ITypeRepairService typeRepairService;

    @Resource
    private IWhHouseSetService houseSetService;

    /**
     * 查询物资类型 -- 根据id
     * 
     * @param typeId 物资类型管理主键
     */
    @Override
    public Type selectTypeByTypeId(Long typeId) {
        return typeMapper.selectTypeByTypeId(typeId);
    }

    @Override
    public List<Integer> selectParentId(MaTypeVo type) {
        return typeMapper.selectParentId(type);
    }

    /**
     * 查询物资类型四级树--前端联动式下拉框
     * @param typeId 类型id
     * @param typeName 类型名称
     */
    @Override
    public List<Type> getEquipmentType(Long typeId, String typeName) {
        List<Type> maTypes = typeMapper.selectMaTypeList("");
        List<Type> list = new ArrayList<>();
        for (Type maType : maTypes) {
            if (maType.getParentId() == 0) {
                list.add(maType);
            }
        }
        //根据父节点获取对应的儿子节点
        for (Type maType : list) {
            List<Type> child = getChild(maTypes, maType.getTypeId());
            maType.setChildren(child);
        }
        return list;
    }


    @Override
    public List<MaTypeSelectVo> selectMaTypeListByHouseId(Long houseId) {
        return typeMapper.selectMaTypeListByHouseId(houseId);
    }

    /**
     * 根据组织树parent_id查询结果
     *
     * @param typeId   父级id
     * @param type 名称筛选
     */
    @Override
    public List<MaTypeVo> getListByParentId(Long typeId, MaTypeVo type) {
        return typeMapper.getListByTypeName(typeId, type);
    }

    @Override
    public List<MaTypeSelectVo> getMaTypeSelectVoListByParentId(Long parentId) {
        return typeMapper.getMaTypeSelectVoListByParentId(parentId);
    }

    /**
     * 查询物资类型管理列表
     * 
     * @param type 物资类型管理
     * @return 物资类型管理
     */
    @Override
    public List<Type> selectTypeList(Type type) {
        if (type != null ) {
            if (StringUtils.isEmpty(type.getDelFlag())) {
                // 如果没赋值，则默认查询正常数据状态
                type.setDelFlag(String.valueOf(DataCodeEnum.NORMAL.getCode()));
            }
            // 如果是顶级节点，则查询所有子节点
            if ("0".equals(type.getLevel())) {
                type.setLevel(null);
            }
        }
        return typeMapper.selectTypeList(type);
    }

    /**
     * 查询物资类型管理列表(库管员)
     *
     * @param type 物资类型管理(库管员)
     * @return 物资类型管理(库管员)
     */
    @Override
    public List<Type> selectTypeList4Keeper(Type type) {
        if (type != null ) {
            if (StringUtils.isEmpty(type.getDelFlag())) {
                // 如果没赋值，则默认查询正常数据状态
                type.setDelFlag(String.valueOf(DataCodeEnum.NORMAL.getCode()));
            }
            // 如果是顶级节点，则查询所有子节点
            if ("0".equals(type.getLevel())) {
                type.setLevel(null);
            }
        }
        return typeMapper.selectTypeList4Keeper(type);
    }

    /**
     * 查询物资类型管理列表(维修员)
     *
     * @param type 物资类型管理(维修员)
     * @return 物资类型管理(维修员)
     */
    @Override
    public List<Type> selectTypeList4Repair(Type type) {
        if (type != null ) {
            if (StringUtils.isEmpty(type.getDelFlag())) {
                // 如果没赋值，则默认查询正常数据状态
                type.setDelFlag(String.valueOf(DataCodeEnum.NORMAL.getCode()));
            }
            // 如果是顶级节点，则查询所有子节点
            if ("0".equals(type.getLevel())) {
                type.setLevel(null);
            }
        }
        return typeMapper.selectTypeList4Repair(type);
    }

    /**
     * 查询物资类型管理列表 -- 并获取父级信息
     *
     * @param type 物资类型管理
     * @return 物资类型管理
     */
    @Override
    public List<MaTypeVo> selectTypeListAndParentInfo(Type type) {
        // 如果是顶级节点，则查询所有子节点
        if (type != null && type.getLevel() != null && "0".equals(type.getLevel())) {
            type.setLevel(null);
        }

        // 拿到数据要处理一下上级信息
        List<MaTypeVo> maTypeVos;
        try {
            maTypeVos = typeMapper.selectTypeListAndParent(type);
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }

        // 检查Mapper集合
        if (maTypeVos == null || maTypeVos.isEmpty()) {
            return new ArrayList<>();
        }


        for (MaTypeVo maTypeVo : maTypeVos) {
            // ------------ 检查 -----------

            // object对象是空的，忽略处理
            if (maTypeVo == null) {
                continue;
            }
            // 没有上级就不需要处理，或者level等级不清晰的也不进行处理
            if (maTypeVo.getParentId() == null || maTypeVo.getLevel() == null) {
                continue;
            }
            // 1级节点已经是顶级，无上级，所以不需要处理
            if ("1".equals(maTypeVo.getLevel())) {
                continue;
            }
            // ------------ 检查结束 -----------


            // 进行数据处理
            switch (maTypeVo.getLevel()) {
                case "2":
                    // 二级节点父级是一级节点，所以要拿到父节点名称，并赋值至ONE_LEVEL_NAME字段
                    maTypeVo.setItemType(maTypeVo.getMaterialName() == null ? "" : maTypeVo.getMaterialName());
                    break;
                case "3":
                    // 三级节点父级是二级节点和一级节点， 要把祖父类型名称放入一级字段，把父类型名称存入二级字段
                    maTypeVo.setItemType(maTypeVo.getMaterialType() == null ? "" : maTypeVo.getMaterialType());
                    maTypeVo.setMaterialType(maTypeVo.getMaterialName() == null ? "" : maTypeVo.getMaterialName());
                    break;
                case "4":
                    // 四级节点父级是三级节点和二级节点和一级节点， 要把祖父类型名称放入一级字段，把父类型名称存入二级字段，子类型名称存入三级字段
                    // 但因为4级节点内循环3次，已按顺序处理，所以此处无需处理
                    break;
            }

        }
        return maTypeVos;
    }

    /**
     * 查询4级加3级的所有物资类型，携带父级信息
     *
     * @param type 参数
     */
    @Override
    public List<MaTypeConfigVo> selectThreeFourLevelTypeListAndParent(Type type) {
        // 查询四级节点列表
        List<MaTypeConfigVo> fourLevelTypeList = typeMapper.selectFourLevelTypeListAndParent(type);
        List<MaTypeConfigVo> threeLevelTypeList = null;

        if (ArrayUtil.isNotEmpty(fourLevelTypeList)) {
            // 查询三级节点列表
            threeLevelTypeList = typeMapper.selectThreeLevelTypeListAndParent(type);
            if (ArrayUtil.isNotEmpty(threeLevelTypeList)) {

                // 使用 HashMap 存储三级节点，以便快速查找
                Map<Long, MaTypeConfigVo> threeLevelTypeMap = new HashMap<>();
                for (MaTypeConfigVo threeLevelType : threeLevelTypeList) {
                    threeLevelTypeMap.put(threeLevelType.getTypeId(), threeLevelType);
                }

                // 外层循环四级节点列表
                for (MaTypeConfigVo fourLevelType : fourLevelTypeList) {
                    // 对4级节点进行必要性检查
                    if (fourLevelType == null || fourLevelType.getParentId() == null) {
                        continue;
                    }
                    // 拿到4级节点的父级id
                    Long fourLevelTypeParentId = fourLevelType.getParentId();
                    // 查找对应的三级节点
                    MaTypeConfigVo threeLevelType = threeLevelTypeMap.get(fourLevelTypeParentId);
                    if (threeLevelType != null) {
                        threeLevelType.getChildren().add(fourLevelType);
                    }
                }
            }
        }
        return threeLevelTypeList;
    }

    /**
     * 新增物资类型管理
     * 
     * @param type 物资类型管理
     * @return 结果
     */
    @Override
    public int insertType(Type type) {
        //根据类型名称判断，去重
        Type maType = typeMapper.queryByNameAndParentId(type.getTypeName(), type.getParentId());
        if (maType != null) {
            throw new RuntimeException("同级下类型名称存在重复！");
        }
        type.setLevel(String.valueOf(Integer.parseInt(type.getLevel()) + 1));
        type.setCreateTime(DateUtils.getNowDate());
        type.setCreateBy(SecurityUtils.getUserId().toString());
        int count = typeMapper.insertType(type);
        if ((type.getParentId()).equals(0L)) {
            // 插入wh_house_set，建立仓库和type的关系
            long newTypeId = type.getTypeId();
            WhHouseSet whHouseSet = new WhHouseSet();
            whHouseSet.setHouseId(type.getHouseId());
            whHouseSet.setTypeId(newTypeId);
            houseSetService.insertWhHouseSet(whHouseSet);
        }
        return count;
    }

    /**
     * 修改物资类型管理
     * 
     * @param type 物资类型管理
     * @return 结果
     */
    @Override
    public int updateType(Type type) {
        //根据类型名称判断，去重
        Type maType = typeMapper.queryByNameAndParentId(type.getTypeName(), type.getParentId());
        if (maType != null && !maType.getTypeId().equals(type.getTypeId())) {
            throw new RuntimeException("同级下类型名称存在重复！");
        }
        type.setUpdateTime(DateUtils.getNowDate());
        type.setUpdateBy(SecurityUtils.getUserId().toString());
        return typeMapper.updateType(type);
    }

    /**
     * 批量删除物资类型管理
     * 
     * @param typeIds 需要删除的物资类型管理主键
     * @return 结果
     */
    @Override
    public int deleteTypeByTypeIds(Long[] typeIds) {
        return typeMapper.logicDeleteTypeByTypeIds(typeIds);
    }

    /**
     * 删除物资类型
     * 
     * @param typeId 物资类型管理主键
     * @return 结果
     */
    @Override
    public AjaxResult deleteTypeByTypeId(Long typeId) {
        //根据id查询删除类型下属是否有关联，有关联无法删除
        List<Type> list = typeMapper.selectById(typeId);
        if (CollectionUtils.isNotEmpty(list)) {
            return AjaxResult.error("该类型下有子类型，无法删除");
        }
        int result = typeMapper.logicDeleteTypeByTypeId(typeId);
        if (result > 0) {
            return AjaxResult.success(HttpCodeEnum.SUCCESS.getMsg(), result);
        }
        return AjaxResult.error(HttpCodeEnum.FAIL.getCode(), HttpCodeEnum.FAIL.getMsg());
    }


    @Override
    public List<TreeSelect> getMaTypeTree(String typeName, String parentId) {
        List<Type> maTypes = typeMapper.selectMaTypeTree();
        List<Type> builtMaTypeList = buildMaTypeTree(maTypes);

        // 查询顶级节点的仓库配置信息

        // 如果没有查询到那么返回空
        return builtMaTypeList.stream()
                .filter(Objects::nonNull)
                .map(this::convertToTreeSelect)
                .collect(Collectors.toList());
    }

    @Override
    public AjaxResult getMaTypeTreeSelect(String typeName, String parentId) {
        // 1.顶级节点及子节点数据全部查询完毕
        List<TreeSelect> maTypeList = this.getMaTypeTree(typeName, parentId);
        // 2.查询所有的仓库配置
        List<WhHouseSet> whHouseSets = houseSetService.selectListByMaType(null);
        // 2.1 定义最终接口返回集合
        List<TreeSelect> treeSelectResultList = new ArrayList<>();

        // 使用HashMap来存储maTypeList，以便快速查找
        Map<Long, TreeSelect> maTypeMap = new HashMap<>();
        for (TreeSelect treeSelect : maTypeList) {
            maTypeMap.put(treeSelect.getId(), treeSelect);
        }

        // 3.遍历所有配置关联
        Map<Long, List<WhHouseSet>> groupedById = whHouseSets.stream().collect(Collectors.groupingBy(WhHouseSet::getHouseId));
        groupedById.forEach((id, itemList) -> {
            TreeSelect thisTree = new TreeSelect(itemList.get(0).getHouseId(),itemList.get(0).getHouseName(),0,null);
            List<TreeSelect> children = new ArrayList<>();
            for (WhHouseSet whHouseSet : itemList) {
                if (whHouseSet == null || whHouseSet.getTypeId() == null) { continue; }
                TreeSelect oneLevelTree = maTypeMap.get(whHouseSet.getTypeId());
                if (oneLevelTree != null) {
                    children.add(oneLevelTree);
                }
            }
            thisTree.setChildren(children);
            treeSelectResultList.add(thisTree);
        });

        return AjaxResult.success(treeSelectResultList);
    }

    /**
     * 通过构造函数将 Type对象 转换为 TreeSelect -- 并递归处理子节点
     * @param type 要进行转换的object对象
     */
    private TreeSelect convertToTreeSelect(Type type) {
        List<TreeSelect> children = type.getChildren().stream()
                .filter(Objects::nonNull)
                .map(this::convertToTreeSelect)
                .collect(Collectors.toList());
        return new TreeSelect(type.getTypeId(), type.getTypeName(), type.getHouseId(), Integer.valueOf(type.getLevel()),type.getParentId(), children);
    }

    /**
     * 递归调用获取子级
     * @param list 集合
     * @param parentId 父级id
     */
    public List<Type> getChild(List<Type> list, Long parentId) {
        List<Type> childList = new ArrayList<Type>();
        for (Type maType : list) {
            Long typeId = maType.getTypeId();
            Long pid = maType.getParentId();
            if (parentId.equals(pid)) {
                List<Type> childLists = getChild(list, typeId);
                maType.setChildren(childLists);
                childList.add(maType);
            }
        }
        return childList;
    }

    /**
     * 构建前端所需要树结构
     *
     * @param maTypeList 部门列表
     * @return 树结构列表
     */
    @Override
    public List<Type> buildMaTypeTree(List<Type> maTypeList) {
        List<Type> returnList = new ArrayList<Type>();
        List<Long> tempList = maTypeList.stream().map(Type::getTypeId).collect(Collectors.toList());
        for (Type maType : maTypeList) {
            // 如果是顶级节点, 遍历该父节点的所有子节点
            if (!tempList.contains(maType.getParentId())) {
                recursionFn(maTypeList, maType);
                returnList.add(maType);
            }
        }
        if (returnList.isEmpty()) {
            returnList = maTypeList;
        }
        return returnList;
    }

    /**
     * 递归列表
     */
    private void recursionFn(List<Type> list, Type t) {
        // 得到子节点列表
        List<Type> childList = getChildList(list, t);
        t.setChildren(childList);
        for (Type tChild : childList) {
            if (hasChild(list, tChild)) {
                recursionFn(list, tChild);
            }
        }
    }

    /**
     * 得到子节点列表
     */
    private List<Type> getChildList(List<Type> list, Type t) {
        List<Type> tlist = new ArrayList<>();
        for (Type n : list) {
            if (StringUtils.isNotNull(n.getParentId()) && n.getParentId().longValue() == t.getTypeId().longValue()) {
                tlist.add(n);
            }
        }
        return tlist;
    }

    /**
     * 判断是否有子节点
     */
    private boolean hasChild(List<Type> list, Type t) {
        return !getChildList(list, t).isEmpty();
    }

//    @Override
//    public AjaxResult getMaTypeConfigList(MaTypeConfigDto maTypeConfigDto) {
//        // 1.把所有物资类型查出来
//        List<MaTypeConfigVo> list = selectThreeFourLevelTypeListAndParent(new Type());
//        // 2.把维修配置信息查出来
//        List<TypeRepair> typeRepairList = typeRepairService.selectTypeRepairListAndUserName(new TypeRepair());
//        // 3.把库管配置信息查出来
//        List<TypeKeeper> typeKeeperList = typeKeeperService.selectTypeKeeperListAndUserName(new TypeKeeper());
//
//        // -------------------  开启数据处理 ---------------------
//
//        // 4.循环所有物资类型,重型数据集合保障只循环一次，减少性能损失
//        for (MaTypeConfigVo typeConfigVo1 : list) {
//            // 1.外层 先对比维修班组
//            for (TypeRepair typeRepair : typeRepairList) {
//                // 2.判断当前维修配置信息中的物资类型id是否等于当前物资类型配置信息中的物资类型id
//                if (Objects.nonNull(typeRepair.getTypeId()) && typeRepair.getTypeId().equals(typeConfigVo1.getTypeId())) {
//                    // 3.如果相等，把维修员信息设置到物资类型配置信息中
//                    typeConfigVo1.setRepairUserId(typeRepair.getUserId());
//                    typeConfigVo1.setRepairUserName(typeRepair.getUserName());
//                    break;
//                }
//            }
//            // 1.外层 再对比库管班组
//            for (TypeKeeper typeKeeper : typeKeeperList) {
//                // 2.判断当前库管配置信息中的物资类型id是否等于当前物资类型配置信息中的物资类型id
//                if (Objects.nonNull(typeKeeper.getTypeId()) && typeKeeper.getTypeId().equals(typeConfigVo1.getTypeId())) {
//                    // 3.如果相等，把库管员信息设置到物资类型配置信息中
//                    typeConfigVo1.setKeeperUserId(typeKeeper.getUserId());
//                    typeConfigVo1.setKeeperUserName(typeKeeper.getUserName());
//                }
//            }
//
//            // 5.判断当前物资类型配置信息是否有子节点
//            if (typeConfigVo1.getChildren() != null) {
//                // 6.有子节点，继续循环子节点，判断子节点是否有维修配置信息
//                for (MaTypeConfigVo typeConfigVo2 : typeConfigVo1.getChildren()) {
//                    // 7.有维修配置信息，把维修员信息设置到子节点中
//                    for (TypeRepair typeRepair : typeRepairList) {
//                        if (Objects.nonNull(typeRepair.getTypeId()) && typeRepair.getTypeId().equals(typeConfigVo2.getTypeId())) {
//                            typeConfigVo2.setRepairUserId(typeRepair.getUserId());
//                            typeConfigVo2.setRepairUserName(typeRepair.getUserName());
//                        }
//                    }
//                }
//
//                // 8.有子节点，继续循环子节点，
//                for (MaTypeConfigVo typeConfigVo3 : typeConfigVo1.getChildren()) {
//                    // 9.判断子节点是否有库管配置信息
//                    for (TypeKeeper typeKeeper : typeKeeperList) {
//                        if (Objects.nonNull(typeKeeper.getTypeId()) && typeKeeper.getTypeId().equals(typeConfigVo3.getTypeId())) {
//                            typeConfigVo3.setKeeperUserId(typeKeeper.getUserId());
//                            typeConfigVo3.setKeeperUserName(typeKeeper.getUserName());
//                        }
//                    }
//                }
//            }
//
//        }
//
//        // -------------------- 数据处理结束 ---------------------
//
//        // TODO: 先暂时取消后续过滤流程
//        if (true) {
//            return AjaxResult.success(list);
//        }
//
//
//        // ------------------- 数据过滤开始 ---------------------
//        if (maTypeConfigDto == null || maTypeConfigDto.getUserId() == null || maTypeConfigDto.getUserId() == 0L) {
//            // 如果参数无效，则返回原始列表
//            return AjaxResult.success(list);
//        }
//
//        List<MaTypeConfigVo> filteredList = new ArrayList<>();
//
//        for (MaTypeConfigVo maTypeConfigVo : list) {
//            if (
//                    maTypeConfigVo.getKeeperUserId().equals(maTypeConfigDto.getUserId()) ||
//                            maTypeConfigVo.getRepairUserId().equals(maTypeConfigDto.getUserId())
//            )
//            {
//                filteredList.add(maTypeConfigVo);
//            }
//        }
//
//        // ------------------- 数据过滤结束 ---------------------
//
//
//        // 返回前端
//        return AjaxResult.success(filteredList);
//    }

    @Override
    public List<MaTypeVo> getMyTypeAndBindUsers(List<MaTypeVo> list) {
        List<TypeRepair> typeRepairList = typeRepairService.selectTypeRepairListAndUserName(new TypeRepair());
        List<TypeKeeper> typeKeeperList = typeKeeperService.selectTypeKeeperListAndUserName(new TypeKeeper());
        for (MaTypeVo maTypeVo : list) {
            if (CollectionUtils.isNotEmpty(typeRepairList)) {
                for (TypeRepair typeRepair : typeRepairList) {
                    if (Objects.nonNull(typeRepair.getTypeId()) && typeRepair.getTypeId().equals(maTypeVo.getTypeId())) {
                        maTypeVo.setRepairUserId(typeRepair.getUserId());
                        maTypeVo.setRepairUserName(typeRepair.getUserName());
                        break;
                    }
                }
            }
            if (CollectionUtils.isNotEmpty(typeKeeperList)) {
                for (TypeKeeper typeKeeper : typeKeeperList) {
                    if (Objects.nonNull(typeKeeper.getTypeId()) && typeKeeper.getTypeId().equals(maTypeVo.getTypeId())) {
                        maTypeVo.setKeeperUserId(typeKeeper.getUserId());
                        maTypeVo.setKeeperUserName(typeKeeper.getUserName());
                    }
                }
            }
        }
        return list;
    }



}
