package com.zd.laboratory.service.impl;

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

import com.zd.common.core.domain.per.PerPrefix;
import com.zd.common.core.exception.ServiceException;
import com.zd.common.core.utils.DateUtils;
import com.zd.common.core.utils.PageHelperUtil;
import com.zd.common.core.utils.SecurityUtils;
import com.zd.common.core.utils.StringUtils;
import com.zd.common.core.utils.poi.ExcelUtil;
import com.zd.common.datascope.annotation.DataScope;
import com.zd.common.security.utils.SaveUtil;

import com.zd.laboratory.domain.vo.LabCheckOptionExcelVo;
import com.zd.laboratory.domain.vo.LabCheckOptionStatisticsVo;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.zd.laboratory.mapper.LabCheckOptionMapper;
import com.zd.laboratory.domain.LabCheckOption;
import com.zd.laboratory.service.ILabCheckOptionService;
import org.springframework.web.multipart.MultipartFile;

import javax.validation.constraints.NotNull;

/**
 * 检查项选项Service业务层处理
 *
 * @author liubo
 * @date 2021-12-30
 */
@Service
public class LabCheckOptionServiceImpl implements ILabCheckOptionService {
    @Autowired
    private LabCheckOptionMapper labCheckOptionMapper;

    /**
     * 查询检查项选项
     *
     * @param id 检查项选项主键
     * @return 检查项选项
     */
    @Override
    public LabCheckOption selectLabCheckOptionById(Long id) {
        return labCheckOptionMapper.selectLabCheckOptionById(id);
    }

    /**
     * 查询检查项选项列表
     *
     * @param labCheckOption 检查项选项
     * @return 检查项选项
     */
    @Override
    @DataScope(deptAlias = "d" , userAlias = "t" , permi = PerPrefix.LABORATORY_CHECKOPTION)
    public List<LabCheckOption> selectLabCheckOptionList(LabCheckOption labCheckOption) {
        labCheckOption.setType(1);
        // 关键字检索，并包含检索的父结点
        List<LabCheckOption> list;
        if(StringUtils.isNotBlank(labCheckOption.getSearchValue())){
            list = getLabCheckBySearchValue(labCheckOption);
        }else {
            list = labCheckOptionMapper.selectLabCheckOptionList(labCheckOption);
        }


        list = getLabCheckOptions(list);

        getLabCheckByLevel(labCheckOption.getLevel(), list);

        return list;
    }

    private List<LabCheckOption> getLabCheckBySearchValue(LabCheckOption labCheckOption) {

        labCheckOption.setName(labCheckOption.getSearchValue());
        List<LabCheckOption> list = labCheckOptionMapper.selectLabCheckOptionList(labCheckOption);
        labCheckOption.setName(null);

        Set<Long> allIds = new HashSet<>();
        Set<Long> childrenIds = new HashSet<>(), parentIds = new HashSet<>();
        getIdsGroup(allIds, list, childrenIds, parentIds, 0);


        // 第一次
        labCheckOption.setIds(new ArrayList<>(parentIds));
        Set<Long> children1Ids = new HashSet<>(), parent1Ids = new HashSet<>();
        getOtherOptions(labCheckOption, allIds, children1Ids, parent1Ids, 1);

        labCheckOption.setIds(null);
        labCheckOption.setpIds(new ArrayList<>(childrenIds));
        getOtherOptions(labCheckOption, allIds, children1Ids, parent1Ids, 2);


        // 第二次
        labCheckOption.setIds(new ArrayList<>(parent1Ids));
        Set<Long> children2Ids = new HashSet<>(), parent2Ids = new HashSet<>();
        getOtherOptions(labCheckOption, allIds, children2Ids, parent2Ids, 1);

        labCheckOption.setIds(null);
        labCheckOption.setpIds(new ArrayList<>(children1Ids));
        getOtherOptions(labCheckOption, allIds, children2Ids, parent2Ids, 2);


        // 第三次
        labCheckOption.setIds(new ArrayList<>(parent2Ids));
        Set<Long> children3Ids = new HashSet<>(), parent3Ids = new HashSet<>();
        getOtherOptions(labCheckOption, allIds, children3Ids, parent3Ids, 1);

        labCheckOption.setIds(null);
        labCheckOption.setpIds(new ArrayList<>(children2Ids));
        getOtherOptions(labCheckOption, allIds, children3Ids, parent3Ids, 2);


        // 第四次
        labCheckOption.setIds(new ArrayList<>(parent3Ids));
        Set<Long> children4Ids = new HashSet<>(), parent4Ids = new HashSet<>();
        getOtherOptions(labCheckOption, allIds, children4Ids, parent4Ids, 1);

        labCheckOption.setIds(null);
        labCheckOption.setpIds(new ArrayList<>(children3Ids));
        getOtherOptions(labCheckOption, allIds, children4Ids, parent4Ids, 2);


        if(allIds.size() > 0){
            labCheckOption.setIds(new ArrayList<>(allIds));
            labCheckOption.setpIds(null);
            list = labCheckOptionMapper.selectLabCheckOptionList(labCheckOption);
        }


        return list;
    }

    @NotNull
    private void getOtherOptions(LabCheckOption labCheckOption, Set<Long> allIds,
                                 Set<Long> childrenIds, Set<Long> parentIds,
                                int type) {

        if(CollectionUtils.isNotEmpty(labCheckOption.getIds()) || CollectionUtils.isNotEmpty(labCheckOption.getpIds())){
            List<LabCheckOption> list = labCheckOptionMapper.selectLabCheckOptionList(labCheckOption);
            getIdsGroup(allIds, list, childrenIds, parentIds, type);
        }
    }

    /**
     * ID 分组
     * @param type 0 全部， 1 向上， 2 向下
     */
    private void getIdsGroup(Set<Long> allIds, List<LabCheckOption> list, Set<Long> childrenIds, Set<Long> parentIds, int type) {
        for (LabCheckOption a : list) {
            allIds.add(a.getId());
            if(a.getLevel() != 4 && (type == 2 || type == 0)){
                childrenIds.add(a.getId());
            }
            if(a.getParentId() != 0 && (type == 1 || type == 0)){
                allIds.add(a.getParentId());
                parentIds.add(a.getParentId());
            }
        }
    }

    private void getLabCheckByLevel(Integer level, List<LabCheckOption> list) {
        if(level != null && level > 0){
            List<LabCheckOption> children1, children2, children3, children4;

            boolean level1 = false, level2 = false,level3 = false;
            for (int i = 0; i < list.size(); i++) {

                // 第二级
                children1 = list.get(i).getChildren();
                if(children1.size() == 0){
                    list.remove(i);
                    i --;
                    continue;
                }
                if(level > 1){
                    for (int i1 = 0; i1 < children1.size(); i1++) {

                        // 第三级
                        children2 = children1.get(i1).getChildren();

                        if(level > 2){

                            if(children2.size() == 0){
                                children1.remove(i1);
                                i1 --;
                                continue;
                            }

                            for (int i2 = 0; i2 < children2.size(); i2++) {

                                // 第四级
                                children3 = children2.get(i2).getChildren();
                                if(level > 3){
                                    if(children3.size() == 0){
                                        children2.remove(i2);
                                        i2 --;
                                    }
                                }else {
                                    level2 = true;
                                    children2.get(i2).setChildren(Collections.emptyList());
                                }
                            }
                        }else {
                            level1 = true;
                            children1.get(i1).setChildren(Collections.emptyList());
                        }
                        if(!level2 && children2.size() == 0){
                            children1.remove(i1);
                            i1 --;
                        }
                    }
                }

                if(!level1 && children1.size() == 0){
                    list.remove(i);
                    i --;
                }
            }
        }
    }

    private void getChildPerms(List<LabCheckOption> optionList, LabCheckOption option){
        // 得到子节点列表
        List<LabCheckOption> childList = getChilds(optionList, option);
        option.setChildren(childList);
        for (LabCheckOption tChild : childList) {
            if (hasChild(optionList, tChild)) {
                getChildPerms(optionList, tChild);
            }
        }
    }

    /**
     * 判断是否有子节点
     */
    private boolean hasChild(List<LabCheckOption> list, LabCheckOption courseChapter) {
        return getChilds(list, courseChapter).size() > 0 ? true : false;
    }

    private List<LabCheckOption> getChilds(List<LabCheckOption> categoryList, LabCheckOption option){
        List<LabCheckOption> tlist = new ArrayList<>();
        Iterator<LabCheckOption> it = categoryList.iterator();
        while (it.hasNext()) {
            LabCheckOption n = it.next();
            if (StringUtils.isNotNull(n.getParentId()) && n.getParentId().longValue() == option.getId().longValue()) {
                tlist.add(n);
            }
        }
        return tlist;
    }

    /**
     * 新增检查项选项
     *
     * @param labCheckOption 检查项选项
     * @return 结果
     */
    @Override
    public LabCheckOption insertLabCheckOption(LabCheckOption labCheckOption) {

        if(labCheckOption.getLevel() == null){
            labCheckOption.setLevel(-1);
        }

        //设置其他公共字段
        SaveUtil.setCommonAttr(labCheckOption);
        labCheckOptionMapper.insertLabCheckOption(labCheckOption);
        if(labCheckOption.getLevel() == 3 && labCheckOption.getType() == 1){
            LabCheckOption checkOption = new LabCheckOption();
            checkOption.setParentId(labCheckOption.getId());
            List<LabCheckOption> list = labCheckOptionMapper.selectLabCheckOptionList(checkOption);
            if(list.size() == 0){
                checkOption.setLevel(4);
                checkOption.setCode("");
                checkOption.setType(labCheckOption.getType());
                checkOption.setName("其他");
                SaveUtil.setCommonAttr(checkOption);
                labCheckOptionMapper.insertLabCheckOption(checkOption);
            }
        }
        return labCheckOption;
    }

    /**
     * 修改检查项选项
     *
     * @param labCheckOption 检查项选项
     * @return 结果
     */
    @Override
    public int updateLabCheckOption(LabCheckOption labCheckOption) {
        labCheckOption.setUpdateTime(DateUtils.getNowDate());
        labCheckOption.setUpdateBy(SecurityUtils.getUsername());
        return labCheckOptionMapper.updateLabCheckOption(labCheckOption);
    }

    /**
     * 批量删除检查项选项
     *
     * @param ids 需要删除的检查项选项主键
     * @return 结果
     */
    @Override
    public int deleteLabCheckOptionByIds(Long[] ids) {

        LabCheckOption labCheckOption = new LabCheckOption();
        for (Long id : ids) {
            labCheckOption.setParentId(id);
            if(CollectionUtils.isNotEmpty(labCheckOptionMapper.selectLabCheckOptionList(labCheckOption))){
                throw new ServiceException("删除失败，请先删除子节点！");
            }
            // TODO 校验该检查性是否使用，如果使用则不能删除
        }

        return labCheckOptionMapper.deleteLabCheckOptionByIds(ids);
    }

    /**
     * 删除检查项选项信息
     *
     * @param id 检查项选项主键
     * @return 结果
     */
    @Override
    public int deleteLabCheckOptionById(Long id) {
        return labCheckOptionMapper.deleteLabCheckOptionById(id);
    }

    @Override
    public void importData(MultipartFile file) {
        try {
            ExcelUtil<LabCheckOptionExcelVo> util = new ExcelUtil<>(LabCheckOptionExcelVo.class);
            List<LabCheckOptionExcelVo> list = util.importExcel(file.getInputStream());
            if(CollectionUtils.isEmpty(list)){
                throw new ServiceException("未检测到数据！");
            }

            LabCheckOption labCheckOption;

            Integer level;
            List<Long> option3Ids = new ArrayList<>();
            for (LabCheckOptionExcelVo labCheckOptionExcelVo : list) {
                level = Integer.parseInt(labCheckOptionExcelVo.getLevel());
                if(level > 4){
                    continue;
                }

                labCheckOption = new LabCheckOption();
                //设置其他公共字段
                SaveUtil.setCommonAttr(labCheckOption);
                labCheckOption.setName(labCheckOptionExcelVo.getName());
                labCheckOption.setParentId(0L);
                labCheckOption.setType(1);
                labCheckOption.setCode(labCheckOptionExcelVo.getCode());
                labCheckOption.setLevel(level);

                labCheckOptionMapper.insertLabCheckOption(labCheckOption);

                labCheckOptionExcelVo.setId(labCheckOption.getId());
                if(level == 3){
                    option3Ids.add(labCheckOption.getId());
                }

            }
            // 再同步关系
            for (LabCheckOptionExcelVo labCheckOptionExcelVo : list) {

                if(org.apache.commons.lang3.StringUtils.isNotBlank(labCheckOptionExcelVo.getParentCode())){
                    labCheckOption = new LabCheckOption();
                    labCheckOption.setId(labCheckOptionExcelVo.getId());
                    for (LabCheckOptionExcelVo checkOptionExcelVo : list) {
                        if(checkOptionExcelVo.getCode().equalsIgnoreCase(labCheckOptionExcelVo.getParentCode())){
                            labCheckOption.setParentId(checkOptionExcelVo.getId());
                            labCheckOptionMapper.updateLabCheckOption(labCheckOption);
                            break;
                        }
                    }
                }
            }

            // 校验是否有4级，如果没有则生成 ‘其他‘ 为第四级
            if(option3Ids.size() > 0){
                labCheckOption = new LabCheckOption();
                LabCheckOption checkOption;
                for (Long option3Id : option3Ids) {
                    labCheckOption.setParentId(option3Id);
                    List<LabCheckOption> options = labCheckOptionMapper.selectLabCheckOptionList(labCheckOption);
                    if(options.size() == 0){
                        checkOption = new LabCheckOption();
                        //设置其他公共字段
                        SaveUtil.setCommonAttr(labCheckOption);
                        checkOption.setParentId(option3Id);
                        checkOption.setLevel(4);
                        checkOption.setCode("");
                        checkOption.setType(1);
                        checkOption.setName("其他");
                        SaveUtil.setCommonAttr(checkOption);
                        labCheckOptionMapper.insertLabCheckOption(checkOption);
                    }
                }
            }

        }catch (Exception e){
            throw new ServiceException("导入失败！" + e.getMessage());
        }
    }

    /**
     * 查询检查项选项列表  -- 临时目录
     */
    @Override
    @DataScope(deptAlias = "d" , userAlias = "t" , permi = PerPrefix.LABORATORY_CHECKOPTION)
    public List<LabCheckOption> selectLabCheckOptionTempList(LabCheckOption labCheckOption) {

        labCheckOption.setType(2);
        List<LabCheckOption> list = labCheckOptionMapper.selectLabCheckOptionTempList(labCheckOption);

        // 所属检查项 信息递归查询 labCheckOption.getParentNames()
        for (LabCheckOption option : list) {
            getParentNames(option, option.getParentId(), null);
        }
        return list;
    }

    @Override
    public void getParentNames(LabCheckOption option, Long parentId, String parentNames) {

        if(parentId != null && parentId != 0){
            LabCheckOption parent0ption = labCheckOptionMapper.selectLabCheckOptionById(parentId);
            if(parent0ption != null){
                if(parentNames != null){
                    parentNames = parent0ption.getName() + " / " + parentNames;
                }else {
                    parentNames = parent0ption.getName();
                }
                option.setParentNames(parentNames);;
                getParentNames(option, parent0ption.getParentId(), parentNames);
            }
        }

    }

    @NotNull
    private List<LabCheckOption> getLabCheckOptions(List<LabCheckOption> list) {
        List<LabCheckOption> options = new ArrayList<>();
        for (LabCheckOption option : list) {
            if(option.getParentId() == 0){
                getChildPerms(list, option);
                options.add(option);
            }
        }

        return options;
    }


    /**
     * 安全隐患统计 柱状图2.4需求
     * @return
     */
    @Override
    @DataScope(deptAlias = "r")
    public Map<String, Object> queryCheckOptionStatistics(LabCheckOptionStatisticsVo labCheckOptionStatisticsVo) {
        List<LabCheckOptionStatisticsVo> list = new ArrayList<>();
        LabCheckOptionStatisticsVo statisticsVo;

        List<LabCheckOption> optionList = selectLabCheckOptionList(new LabCheckOption());
        // 最多四级， 暂循环处理
        int count = 0;
        for (LabCheckOption option1 : optionList) {

            statisticsVo = new LabCheckOptionStatisticsVo();
            statisticsVo.setOptionId(option1.getId());
            statisticsVo.setOptionName(option1.getName());

            labCheckOptionStatisticsVo.setIds(getAllChildrenIds(option1));
            statisticsVo.setCount(labCheckOptionMapper.queryCheckOptionStatistics(labCheckOptionStatisticsVo));

            count += statisticsVo.getCount();
            list.add(statisticsVo);
        }

        list = list.stream().sorted(Comparator.comparing(LabCheckOptionStatisticsVo::getCount).reversed()).collect(Collectors.toList());

        Map<String, Object> result = new HashMap<>();
        result.put("count", count);
        result.put("list", list);

        return result;
    }

    /**
     * 安全隐患统计 详情页列表2.4需求
     */
    @Override
    public List<LabCheckOptionStatisticsVo> queryCheckOptionStatisticDtails(LabCheckOptionStatisticsVo labCheckOptionStatisticsVo) {

        if(labCheckOptionStatisticsVo.getOptionId() != null){

            List<LabCheckOption> optionList = selectLabCheckOptionList(new LabCheckOption());
            for (LabCheckOption option1 : optionList) {
                if(labCheckOptionStatisticsVo.getOptionId().equals(option1.getId()+"")){

                    labCheckOptionStatisticsVo.setIds(getAllChildrenIds(option1));
                    break;
                }
            }

        }

        PageHelperUtil.startPage();
        return labCheckOptionMapper.queryCheckOptionStatisticDtails(labCheckOptionStatisticsVo);
    }

    private List<Long> getAllChildrenIds(LabCheckOption option1) {
        List<Long> optionIds = new ArrayList<>();
        optionIds.add(option1.getId());

        List<LabCheckOption> children1 = option1.getChildren();
        if(children1.size() > 0){
            for (LabCheckOption option2 : children1) {
                optionIds.add(option2.getId());

                List<LabCheckOption> children2 = option2.getChildren();
                if(children2.size() > 0){
                    for (LabCheckOption option3 : children2) {
                        optionIds.add(option3.getId());

                        List<LabCheckOption> children3 = option3.getChildren();
                        if(children3.size() > 0){
                            for (LabCheckOption option4 : children3) {
                                optionIds.add(option4.getId());
                            }
                        }
                    }
                }
            }
        }
        return optionIds;
    }
}
