package com.yeejoin.equipmanage.service.impl;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yeejoin.amos.boot.biz.common.bo.ReginParams;
import com.yeejoin.amos.boot.biz.common.utils.RedisUtils;
import com.yeejoin.equipmanage.common.entity.EquipmentCategory;
import com.yeejoin.equipmanage.common.entity.Industry;
import com.yeejoin.equipmanage.common.entity.vo.EquipTypeAmountVO;
import com.yeejoin.equipmanage.common.entity.vo.EquipmentCategoryCountVO;
import com.yeejoin.equipmanage.common.entity.vo.EquipmentCategoryTypeTreeVO;
import com.yeejoin.equipmanage.common.enums.BillContentEnum;
import com.yeejoin.equipmanage.common.enums.IndustryEnum;
import com.yeejoin.equipmanage.common.exception.CommonException;
import com.yeejoin.equipmanage.common.utils.StringUtil;
import com.yeejoin.equipmanage.common.vo.IndustryVo;
import com.yeejoin.equipmanage.context.SpringContextHolder;
import com.yeejoin.equipmanage.event.EquipmentTreeListEvent;
import com.yeejoin.equipmanage.mapper.EquipmentCategoryMapper;
import com.yeejoin.equipmanage.service.IEquipmentCategoryService;
import com.yeejoin.equipmanage.service.IIndustryService;
import com.yeejoin.equipmanage.service.IStockBillDetailService;

/**
 * 装备分类 服务实现类
 *
 * @author wujiang
 * @date 2020-07-07
 */
@Service
public class EquipmentCategoryServiceImpl extends ServiceImpl<EquipmentCategoryMapper, EquipmentCategory>
        implements IEquipmentCategoryService {

    @Autowired
    private EquipmentCategoryMapper equipmentCategoryMapper;
    @Autowired
    private IStockBillDetailService stockBillDetailService;
    @Value("${equipment.type}")
    String equipmentCategoryLeftTypeCode;
    @Autowired
    IIndustryService iIndustryService;
    @Autowired
    private RedisUtils redisUtils;

    private static final String equipmentTreeListZB = "equipmentTreeListZB";
    private static final String equipmentTreeListCL = "equipmentTreeListCL";

    /**
     * Add default industry code.
     * Modified by tb
     *
     * @param equipmentCategory
     * @return
     */
    @Override
    public EquipmentCategory saveEquipmentCategory(EquipmentCategory equipmentCategory) {

        String name = equipmentCategory.getName();
        if (name == null || "".equals(name.trim())) {
            throw new CommonException(0, "名称不能为空！");
        }

        QueryWrapper<EquipmentCategory> queryWrapper1 = new QueryWrapper<EquipmentCategory>();
        queryWrapper1.lambda().eq(EquipmentCategory::getName, name).eq(EquipmentCategory::getIndustryCode,
                equipmentCategory.getIndustryCode());
        EquipmentCategory eqc = this.getOne(queryWrapper1);
        if (eqc != null) {
            throw new CommonException(0, "名称重复");
        }

        String code = null;
        Map<String, Object> map = new HashMap<>();
        Long id = equipmentCategory.getParentId();
        EquipmentCategory parentEqc = this.getById(id);
        if (ObjectUtils.isEmpty(parentEqc)) {
            throw new CommonException(0, "请先选择上级装备分类!");
        }

        if (parentEqc.getIsConsumptive() && !equipmentCategory.getIsConsumptive()) {
            throw new CommonException(0, "父级为消耗型，子类别必须必须为消耗型！");
        }

        // 级别
        String parentCode = parentEqc.getCode();
        Long parentId = parentEqc.getId();
        String level = ObjectUtils.isEmpty(parentEqc.getParentId()) ? "1"
                : (this.baseMapper.getEquipCategoryLevelByParentId(parentEqc.getId()) + "");

        if ("5".equals(level)) {
            throw new CommonException(0, "该类下不允许插入装备分类信息，请重新选择上级分类！");
        }

        if (name != null && name.contains("其他")) {
            QueryWrapper<EquipmentCategory> queryWrapper2 = new QueryWrapper<EquipmentCategory>();
            queryWrapper2.lambda().eq(EquipmentCategory::getParentId, parentId).like(EquipmentCategory::getName, "其他");
            List<EquipmentCategory> list = this.list(queryWrapper2);
            if (!list.isEmpty()) {
                throw new CommonException(0, "该级别下只能包含一种【其他】分类！");
            }
            switch (level) {
                case "1":
                    code = String.valueOf(Long.valueOf(parentCode) + 9000000);
                    break;
                case "2":
                    code = String.valueOf(Long.valueOf(parentCode) + 990000);
                    break;
                case "3":
                    code = String.valueOf(Long.valueOf(parentCode) + 9900);
                    break;
                case "4":
                    code = String.valueOf(Long.valueOf(parentCode) + 99);
                    break;
                default:
                    throw new CommonException(0, "该类下不允许插入装备分类信息，请重新选择上级分类！");
            }
            equipmentCategory.setCode(code);
            this.save(equipmentCategory);
            return equipmentCategory;
        }

        List<Map<String, Object>> result = this.baseMapper.getEquipCategoryCodeListByParentId(parentId);
        if (result.isEmpty()) {
            throw new CommonException(0, "编码生成错误，请重新选择上级分类！");
        }
        code = result.get(0).get("newCode").toString();
        switch (level) {
            case "1":
                if (String.valueOf(Long.valueOf(parentCode) + 9000000).equals(code)) {
                    throw new CommonException(0, "该级别下普通类别已达到上限！");
                }
                break;
            case "2":
                if (String.valueOf(Long.valueOf(parentCode) + 990000).equals(code)) {
                    throw new CommonException(0, "该级别下普通类别已达到上限！");
                }
                break;
            case "3":
                if (String.valueOf(Long.valueOf(parentCode) + 9900).equals(code)) {
                    throw new CommonException(0, "该级别下普通类别已达到上限！");
                }
                break;
            case "4":
                if (String.valueOf(Long.valueOf(parentCode) + 99).equals(code)) {
                    throw new CommonException(0, "该级别下普通类别已达到上限！");
                }
                break;
        }
        equipmentCategory.setCode(code);
        // 如果不传行业id则行业类型默认为消防设备
        if (!StringUtil.isNotEmpty(equipmentCategory.getIndustryCode())) {
            equipmentCategory.setIndustryCode(IndustryEnum.EQUIP.getCode());
        }
        equipmentCategoryMapper.insert(equipmentCategory);
        // 更新缓存
        SpringContextHolder.publishEvent(new EquipmentTreeListEvent(this,equipmentCategory));
        return equipmentCategory;
    }

    @Override
    public List<EquipmentCategory> tree(String type) {
//        this.getEquipmentCategoryList(Integer.valueOf(2));
        List<EquipmentCategory> list = null;

        // 判断缓存中是否有该数据
        if (BillContentEnum.ZB.getCode().equals(type)) {
            boolean treeListFlagZB = redisUtils.hasKey(equipmentTreeListZB);
            if (treeListFlagZB) {
                if (redisUtils.get(equipmentTreeListZB) != null) {
                    list = JSONObject.parseArray(redisUtils.get(equipmentTreeListZB).toString(),EquipmentCategory.class);
                }
            } else {
                // 缓存中没有, 读取并写入缓存
                list = this.getEquipmentCategoryEquipmentList();
                redisUtils.set(equipmentTreeListZB, JSONObject.toJSONString(list),0);
            }
        } else if (BillContentEnum.CL.getCode().equals(type)) {
            boolean treeListFlagCL = redisUtils.hasKey(equipmentTreeListCL);
            if (treeListFlagCL) {
                if (redisUtils.get(equipmentTreeListCL) != null) {
                    list = JSONObject.parseArray(redisUtils.get(equipmentTreeListCL).toString(),EquipmentCategory.class);
                }
            } else {
                // 缓存中没有, 读取并写入缓存
                list = this.getEquipmentCategoryCarList();
                redisUtils.set(equipmentTreeListCL, JSONObject.toJSONString(list),0);
            }
        }
        return buildByRecursive(list);
    }

    /**
     * 读取非车辆装备
     * @return
     */
    public List<EquipmentCategory> getEquipmentCategoryEquipmentList() {
        return this.baseMapper.getEquipmentCategoryEquipmentList();
    }

    /**
     * 读取车辆装备
     * @return
     */
    public List<EquipmentCategory> getEquipmentCategoryCarList() {
        return this.baseMapper.getEquipmentCategoryCarList();
    }

    @Override
    public List<EquipmentCategoryCountVO> typeCount() {
        //父类型所有数据
        QueryWrapper<EquipmentCategory> wrapper = new QueryWrapper<>();
        wrapper.isNull("parent_id");
        List<EquipmentCategory> list = this.baseMapper.selectList(wrapper);
        List<EquipmentCategoryCountVO> equipmentCategoryCountVOS = new ArrayList<>();
        //获取个人信息
        ReginParams reginParams = stockBillDetailService.getSelectedOrgInfo();
        //统计父类所有子类数据
        list.forEach(x -> {
            EquipmentCategoryCountVO equipmentCategoryCountVO = new EquipmentCategoryCountVO();
            equipmentCategoryCountVO.setCode(x.getCode());
            equipmentCategoryCountVO.setId(x.getId());
            equipmentCategoryCountVO.setName(x.getName());
            equipmentCategoryCountVO.setValue(equipmentCategoryMapper.selectCategoryAmount(x.getIndustryCode(),
                    x.getCode().substring(0, 1), reginParams.getCompany().getOrgCode()));
            equipmentCategoryCountVOS.add(equipmentCategoryCountVO);
        });
        return equipmentCategoryCountVOS;
    }

    @Override
    public List<EquipmentCategoryTypeTreeVO> getTypeTree(Long id) {
        List<EquipmentCategoryTypeTreeVO> equipmentCategoryTypeTreeVOS = new ArrayList<>();
        //第一层类型
        QueryWrapper<EquipmentCategory> wrapper = new QueryWrapper<>();
        wrapper.eq("parent_id", id);
        List<EquipmentCategory> list = this.baseMapper.selectList(wrapper);
        list.forEach(x -> {
            //第二层
            List<EquipmentCategoryTypeTreeVO> equipmentCategoryTypeTreeVOS1 = new ArrayList<>();
            QueryWrapper<EquipmentCategory> wrapper2 = new QueryWrapper<>();
            wrapper2.eq("parent_id", x.getId());
            List<EquipmentCategory> list2 = this.baseMapper.selectList(wrapper2);
            //第三层
            List<EquipmentCategoryTypeTreeVO> equipmentCategoryTypeTreeVOS2 = new ArrayList<>();
            list2.forEach(y -> {

                QueryWrapper<EquipmentCategory> wrapper3 = new QueryWrapper<>();
                wrapper3.eq("parent_id", y.getId());
                List<EquipmentCategory> list3 = this.baseMapper.selectList(wrapper3);
                list3.forEach(z -> {
                    QueryWrapper<EquipmentCategory> wrapper4 = new QueryWrapper<>();
                    wrapper4.eq("parent_id", z.getId());
                    List<EquipmentCategory> list4 = this.baseMapper.selectList(wrapper4);
                    List<EquipmentCategoryTypeTreeVO> equipmentCategoryTypeTreeVOS3 = new ArrayList<>();
                    list4.forEach(m -> {
                        EquipmentCategoryTypeTreeVO equipmentCategoryTypeTreeVO4 = new EquipmentCategoryTypeTreeVO();
                        equipmentCategoryTypeTreeVO4.setEquipmentClassificationCode(m.getCode());
                        equipmentCategoryTypeTreeVO4.setEquipmentClassificationId(m.getId());
                        equipmentCategoryTypeTreeVO4.setEquipmentClassificationName(m.getName());
                        equipmentCategoryTypeTreeVO4.setHasLowerClassification(false);
                        equipmentCategoryTypeTreeVO4.setHierarchy(8);
                        equipmentCategoryTypeTreeVOS3.add(equipmentCategoryTypeTreeVO4);
                    });
                    EquipmentCategoryTypeTreeVO equipmentCategoryTypeTreeVO3 = new EquipmentCategoryTypeTreeVO();
                    equipmentCategoryTypeTreeVO3.setEquipmentClassificationCode(z.getCode());
                    equipmentCategoryTypeTreeVO3.setEquipmentClassificationId(z.getId());
                    equipmentCategoryTypeTreeVO3.setEquipmentClassificationName(z.getName());
                    //是否有子节点
                    if (equipmentCategoryTypeTreeVOS3.size() > 0) {
                        equipmentCategoryTypeTreeVO3.setHasLowerClassification(true);
                    } else {
                        equipmentCategoryTypeTreeVO3.setHasLowerClassification(false);
                    }
                    equipmentCategoryTypeTreeVO3.setHierarchy(6);
                    equipmentCategoryTypeTreeVO3.setChildren(equipmentCategoryTypeTreeVOS3);
                    equipmentCategoryTypeTreeVOS2.add(equipmentCategoryTypeTreeVO3);
                });
                EquipmentCategoryTypeTreeVO equipmentCategoryTypeTreeVO2 = new EquipmentCategoryTypeTreeVO();
                equipmentCategoryTypeTreeVO2.setEquipmentClassificationCode(y.getCode());
                equipmentCategoryTypeTreeVO2.setEquipmentClassificationId(y.getId());
                equipmentCategoryTypeTreeVO2.setEquipmentClassificationName(y.getName());
                equipmentCategoryTypeTreeVO2.setHierarchy(4);
                //是否有子节点
                if (equipmentCategoryTypeTreeVOS2.size() > 0) {
                    equipmentCategoryTypeTreeVO2.setHasLowerClassification(true);
                } else {
                    equipmentCategoryTypeTreeVO2.setHasLowerClassification(false);
                }
                equipmentCategoryTypeTreeVO2.setChildren(equipmentCategoryTypeTreeVOS2);
                equipmentCategoryTypeTreeVOS1.add(equipmentCategoryTypeTreeVO2);
            });
            EquipmentCategoryTypeTreeVO equipmentCategoryTypeTreeVO = new EquipmentCategoryTypeTreeVO();
            equipmentCategoryTypeTreeVO.setEquipmentClassificationCode(x.getCode());
            equipmentCategoryTypeTreeVO.setEquipmentClassificationId(x.getId());
            equipmentCategoryTypeTreeVO.setEquipmentClassificationName(x.getName());
            equipmentCategoryTypeTreeVO.setHierarchy(2);
            //是否有子节点
            if (equipmentCategoryTypeTreeVOS1.size() > 0) {
                equipmentCategoryTypeTreeVO.setHasLowerClassification(true);
            } else {
                equipmentCategoryTypeTreeVO.setHasLowerClassification(false);
            }
            equipmentCategoryTypeTreeVO.setChildren(equipmentCategoryTypeTreeVOS1);
            equipmentCategoryTypeTreeVOS.add(equipmentCategoryTypeTreeVO);
        });
        return equipmentCategoryTypeTreeVOS;
    }

    @Override
    public List<EquipTypeAmountVO> CategoryAmountList(IPage<EquipmentCategory> page, int hierarchy, String codeHead, String equipmentName) {
        //获取个人信息
        ReginParams reginParams = stockBillDetailService.getSelectedOrgInfo();
        return equipmentCategoryMapper.CategoryAmountList(page, hierarchy, codeHead, reginParams.getCompany().getOrgCode(), equipmentName);
    }

    @Override
    public String checkFather(List<String> ids) {
        for (String id : ids) {
            int is = equipmentCategoryMapper.islvlOne(id);
            if (is == 1) {
                int i = equipmentCategoryMapper.checkFather(id);
                if (i > 0) {
                    return "存在父节点";
                }
            }
        }
        return "";
    }

    @Override
    public int checkUsed(List<String> ids) {
        for (String id : ids) {
            int count = equipmentCategoryMapper.checkUsed(id);
            if (count > 0) {
                return 1;
            }
        }
        return 0;
    }

    /**
     * 使用递归方法建树
     *
     * @param treeNodes
     * @return
     */
    private List<EquipmentCategory> buildByRecursive(List<EquipmentCategory> treeNodes) {
        List<EquipmentCategory> trees = new ArrayList<EquipmentCategory>();
        for (EquipmentCategory treeNode : treeNodes) {
            if (null == treeNode.getParentId()) {
                trees.add(findChildren(treeNode, treeNodes));
            }
        }
        return trees;
    }

    /**
     * 递归查找子节点
     *
     * @param treeNodes
     * @return
     */
    private EquipmentCategory findChildren(EquipmentCategory treeNode, List<EquipmentCategory> treeNodes) {
        for (EquipmentCategory it : treeNodes) {
            if (treeNode.getId().equals(it.getParentId())) {
                if (treeNode.getChildren() == null) {
                    treeNode.setChildren(new ArrayList<EquipmentCategory>());
                }
                treeNode.getChildren().add(findChildren(it, treeNodes));
            }
        }
        return treeNode;
    }

    @Override
    public List<EquipmentCategory> getEquipmentCategoryList(Integer head) {
        return this.baseMapper.getEquipmentCategoryList(head);
    }

    @Override
    public List<Long> getAllChildCategoryIdList(Long categoryId) {
        return this.baseMapper.getAllChildCategoryIdList(categoryId);
    }

    @Override

    public List<EquipmentCategory> getColaEquipmentCategoryList(Integer head, String industryCode){
        return this.baseMapper.getColaEquipmentCategoryList(head, industryCode);
    }

    /**
     * 获取全量树数据
     * @return
     */
    public List<IndustryVo> getTreeListAll() {

        List<EquipmentCategory> equipmentCategories = getColaEquipmentCategoryList(Integer.valueOf(equipmentCategoryLeftTypeCode), null);
        List<EquipmentCategory> list = new ArrayList<>();
        List<IndustryVo> result = new ArrayList<>();
        Map<String, List<EquipmentCategory>> tmpMap = new HashMap<String, List<EquipmentCategory>>();
        equipmentCategories.forEach(action -> {
            if (action.getParentId() == null) {
                list.add(action);
            } else {
                if (tmpMap.get(action.getParentId().toString()) == null) {
                    ArrayList<EquipmentCategory> tmpList = new ArrayList<EquipmentCategory>();
                    tmpList.add(action);
                    tmpMap.put(action.getParentId().toString(), tmpList);
                } else {
                    if (!tmpMap.get(action.getParentId().toString()).contains(action)) {
                        tmpMap.get(action.getParentId().toString()).add(action);
                    }
                }
            }
        });
        getChildrenList(list, tmpMap);
        List<Industry> industries = new ArrayList<>();
        industries = iIndustryService.list().stream().sorted(Comparator.comparing(Industry::getIndustrySort)).collect(Collectors.toList());
        for (Industry industry : industries) {
            IndustryVo industryVo = new IndustryVo();
            List<EquipmentCategory> categoriesList = new ArrayList<>();
            BeanUtils.copyProperties(industry, industryVo);
            for (EquipmentCategory category : list) {
                if (industry.getCode().equals(category.getIndustryCode())) {
                    category.setParentId(industry.getId());
                    categoriesList.add(category);
                }
            }
            if (0 < categoriesList.size()) {
                industryVo.setHasLowerClassification(true);
                industryVo.setChildren(categoriesList);
            }
            industryVo.setIndustryCode(industry.getCode());
            result.add(industryVo);
        }
        return result;
    }

    /**
     *
     * 获取子节点
     */
    private void getChildrenList(List<EquipmentCategory> list, Map<String, List<EquipmentCategory>> tmpMap) {
        for (EquipmentCategory equipmentCategory : list) {
            if (tmpMap.get(equipmentCategory.getId().toString()) != null
                    && tmpMap.get(equipmentCategory.getId().toString()).size() > 0) {
                List<EquipmentCategory> equipcliss = tmpMap.get(equipmentCategory.getId().toString());
                equipmentCategory.setHasLowerClassification(true);
                equipmentCategory.setChildren(equipcliss);
                getChildrenList(equipcliss, tmpMap);
            }
        }
    }

    /**
     * 根据行业code获取树
     * @param code
     * @return
     */
    public List<EquipmentCategory> getIndustryTreeList(String code) {
        List<EquipmentCategory> list = new ArrayList<>();
        List<EquipmentCategory> equipmentCategories = getColaEquipmentCategoryList(Integer.valueOf(equipmentCategoryLeftTypeCode), code);
        Map<String, List<EquipmentCategory>> tmpMap = new HashMap<String, List<EquipmentCategory>>();
        equipmentCategories.forEach(action -> {
            if (action.getParentId() == null) {
                action.setLevel("0");
                list.add(action);
            } else {
                if (tmpMap.get(action.getParentId().toString()) == null) {
                    ArrayList<EquipmentCategory> tmplist = new ArrayList<EquipmentCategory>();
                    action.setLevel("2");
                    tmplist.add(action);
                    tmpMap.put(action.getParentId().toString(), tmplist);
                } else {
                    if (!tmpMap.get(action.getParentId().toString()).contains(action)) {
                        action.setLevel("2");
                        tmpMap.get(action.getParentId().toString()).add(action);
                    }
                }
            }
        });
        for(EquipmentCategory type:list){
            Long category = type.getId();
            List<EquipmentCategory> equipment = tmpMap.get(category.toString());
            if(equipment!=null){
                for(EquipmentCategory a:equipment){
                    a.setLevel("1");
                }
            }

        }
        getChildrenList(list, tmpMap);
        return list;

}

}
