package com.ruoyi.project.business.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.importExcel.excel.helper.BasicTableInfoHelper;
import com.ruoyi.common.importExcel.excel.tempInfo.ParaLibraryExcel;
import com.ruoyi.common.importExcel.excel.tempInfo.ParaLibraryExportHelper;
import com.ruoyi.common.importExcel.excel.tempInfo.ParaSelectExcel;
import com.ruoyi.common.importExcel.utils.ExcelUtils;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.project.business.domain.TpAreaParaSelectItem;
import com.ruoyi.project.business.domain.TpParaLibrary;
import com.ruoyi.project.business.domain.TpParaSelectItem;
import com.ruoyi.project.business.mapper.*;
import com.ruoyi.project.business.service.ITpParaLibraryService;
import com.ruoyi.project.system.domain.SysDictData;
import com.ruoyi.project.system.mapper.SysDictDataMapper;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.ruoyi.common.utils.Tools.splitList;

/**
 * 参数Service业务层处理
 *
 * @author ruoyi
 * @date 2024-04-23
 */
@Service
public class TpParaLibraryServiceImpl extends ServiceImpl<TpParaLibraryMapper, TpParaLibrary> implements ITpParaLibraryService {
    @Resource
    private TpParaLibraryMapper tpParaLibraryMapper;
    @Resource
    TpParaSelectItemMapper tpParaSelectItemMapper;
    @Resource
    SysDictDataMapper sysDictDataMapper;
    @Resource
    private TpParabarDetailValueMapper tpParabarDetailValueMapper;
    @Resource
    private TpAreaElevatorModelParaMapper tpAreaElevatorModelParaMapper;
    @Resource
    private TpCaseElevatorMapper tpCaseElevatorMapper;
    @Resource
    private TpParaValidationElevatorMapper tpParaValidationElevatorMapper;
    /**
     * 查询参数
     *
     * @param id 参数主键
     * @return 参数
     */
    @Override
    public TpParaLibrary selectTpParaLibraryById(Long id) {
        return tpParaLibraryMapper.selectTpParaLibraryById(id);
    }

    /**
     * 查询参数列表
     *
     * @param tpParaLibrary 参数
     * @return 参数
     */
    @Override
    public List<TpParaLibrary> selectTpParaLibraryList(TpParaLibrary tpParaLibrary) {
        return tpParaLibraryMapper.selectTpParaLibraryList(tpParaLibrary);
    }

    /**
     * 查询参数包的参数
     *
     * @param parabarId 参数包ID
     * @return 参数集合
     */
    public List<TpParaLibrary> selectTpParaLibraryByParabarId(Long parabarId) {
        return tpParaLibraryMapper.selectTpParaLibraryByParabarId(parabarId);
    }

    /**
     * 新增参数
     *
     * @param tpParaLibrary 参数
     * @return 结果
     */
    @Override
    public int insertTpParaLibrary(TpParaLibrary tpParaLibrary) {
        //获取所有参数转化为MAP
        List<TpParaLibrary> paraList = tpParaLibraryMapper.selectTpParaLibraryList(new TpParaLibrary());
        Map<String, String> paraMap = paraList.stream().collect(Collectors.toMap(TpParaLibrary::getParaCode, TpParaLibrary::getParaName, (key1, key2) -> key1));

        if (paraMap.containsKey(tpParaLibrary.getParaCode())) {
            throw new ServiceException("该参数编码已存在");
        }
        if (paraMap.containsValue(tpParaLibrary.getParaName())) {
            throw new ServiceException("该参数名称已存在");
        }
        Date nowDate = DateUtils.getNowDate();
        tpParaLibrary.setCreateBy(SecurityUtils.getUserId().toString());
        tpParaLibrary.setCreateTime(nowDate);
        tpParaLibrary.setUpdateBy(SecurityUtils.getUserId().toString());
        tpParaLibrary.setUpdateTime(nowDate);
        return tpParaLibraryMapper.insertTpParaLibrary(tpParaLibrary);
    }

    /**
     * 修改参数
     *
     * @param tpParaLibrary 参数
     * @return 结果
     */
    @Override
    public int updateTpParaLibrary(TpParaLibrary tpParaLibrary) {
        //获取所有参数转化为MAP
        List<TpParaLibrary> paraList = tpParaLibraryMapper.selectTpParaLibraryList(new TpParaLibrary());
        //排除自己
        List<TpParaLibrary> paraListNew = paraList.stream().filter(it-> !tpParaLibrary.getId().equals(it.getId())).collect(Collectors.toList());
        Map<String, String> paraMap = paraListNew.stream().collect(Collectors.toMap(TpParaLibrary::getParaCode, TpParaLibrary::getParaName, (key1, key2) -> key1));

        if (paraMap.containsKey(tpParaLibrary.getParaCode())) {
            throw new ServiceException("该参数编码已存在");
        }

        tpParaLibrary.setUpdateTime(DateUtils.getNowDate());
        return tpParaLibraryMapper.updateTpParaLibrary(tpParaLibrary);
    }

    /**
     * 批量删除参数
     *
     * @param ids 需要删除的参数主键
     * @return 结果
     */
    @Override
    public int deleteTpParaLibraryByIds(Long[] ids) {
        // todo 删除参数库前需要校验是否可以删除
        Long id = ids[0];
        //检查是否被参数包使用
        int i = tpParabarDetailValueMapper.selectBarCount(id);
        if(i>0){
            //返回无法删除
//            throw new ServiceException(MessageUtils.message("common.hasBar"));
            throw new ServiceException("该参数已被参数包使用，无法删除！");
        }
        //检查是否被区域梯形使用
        int j = tpAreaElevatorModelParaMapper.selectAreaCount(id);
        if(j>0){
            //返回无法删除
//            throw new ServiceException(MessageUtils.message("common.hasAreaPara"));
            throw new ServiceException("该参数已被区域梯形使用，无法删除！");
        }
        //检查是否被校验规则使用(校验规则基于区域梯形)

        //检查是否被参数联动使用
        int k = tpCaseElevatorMapper.selectCaseCount(id);
        if(k>0){
            //返回无法删除
//            throw new ServiceException(MessageUtils.message("common.hasValidationPara"));
            throw new ServiceException("该参数已被参数联动使用，无法删除！");
        }
        return tpParaLibraryMapper.deleteTpParaLibraryByIdsReal(ids);
    }

    /**
     * 删除参数信息
     *
     * @param id 参数主键
     * @return 结果
     */
    @Override
    public int deleteTpParaLibraryById(Long id) {
        return tpParaLibraryMapper.deleteTpParaLibraryById(id);
    }

    /**
     * 修改参数状态
     *
     * @param tpParaLibrary 参数
     * @return 结果
     */
    @Override
    public int updateParaStatus(TpParaLibrary tpParaLibrary) {

        if ("1".equals(tpParaLibrary.getStatus())) {
            int usedCount = tpParaLibraryMapper.checkParaChangeAllowed(tpParaLibrary.getId());

            if (usedCount > 0) {
                throw new ServiceException(MessageUtils.message("paraLibrary.usingMessage"));
//                throw new ServiceException("该参数正在使用中，请确认！");
            }
        }
        tpParaLibrary.setUpdateBy(SecurityUtils.getStrUserId());
        tpParaLibrary.setUpdateTime(DateUtils.getNowDate());
        return tpParaLibraryMapper.updateTpParaLibrary(tpParaLibrary);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<String> insertTpParaLibraryExcel(List<ParaLibraryExcel> tpParaLibrarys) {
        List<String> errList = new ArrayList<>();
        int i = 0;
        //todo 处理数据,需要把字典类型数据替换为value
        Date now = DateUtils.CNTimeDate(new Date(), SecurityUtils.getTimeZone());
        List<TpParaLibrary> mainList = new ArrayList<>();
        long sort = 0L;
        //获取参数库最大的sort
        sort = tpParaLibraryMapper.getMaxSort()+1;
        //批量新增主表数据
        for (ParaLibraryExcel main : tpParaLibrarys) {
            TpParaLibrary item = new TpParaLibrary();
            BeanUtils.copyProperties(main, item);
            item.setSortNumber(sort);
            item.setStatus("0");
            //设置创建人时间
            item.setCreateBy(SecurityUtils.getUserId() + "");
            item.setCreateTime(now);
            mainList.add(item);
            sort += 1L;
        }

        //todo 新增之前验证重复
        //批量新增主表
        i = tpParaLibraryMapper.InsertBySQL(mainList);
        if (i <= 0) {
            //直接回滚
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return errList;
        }
        List<TpParaSelectItem> selectList = new ArrayList<>();
        //循环主表找到子表数据并设定主表id,并设置子表数据

        for (ParaLibraryExcel main : tpParaLibrarys) {
            long sortS = 0L;
            for (TpParaLibrary id : mainList) {
                if (id.getParaCode().equals(main.getParaCode())) {
                    main.setId(id.getId());
                    break;
                }
            }
            //只有select新增子表
            if ("02".equals(main.getInputType()) || "04".equals(main.getInputType())) {
                for (ParaSelectExcel select : main.getSelectVOS()) {
                    TpParaSelectItem selectItem = new TpParaSelectItem();
                    BeanUtils.copyProperties(select, selectItem);
                    selectItem.setParaId(main.getId());
                    selectItem.setSortNumber(sortS);
                    selectItem.setCreateBy(SecurityUtils.getUserId() + "");
                    selectItem.setCreateTime(now);
                    selectList.add(selectItem);
                    sortS += 1L;
                }
            }
        }
        int j = 0;
        //todo 新增之前验证重复
        //分批次插入
        List<List<TpParaSelectItem>> list = splitList(selectList, 50);
        if (list != null && list.size() > 0) {
            for (List<TpParaSelectItem> listSplit : list){
                j += tpParaSelectItemMapper.InsertBySQL(listSplit);
            }
            if (j <= 0) {
                //直接回滚
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return errList;
            }
        }

        return errList;
    }


    @Override
    public ExcelUtils.UploadResult<ParaLibraryExcel> checkParaLibrary(BasicTableInfoHelper tableInfo, List<ParaLibraryExcel> list) {
        //获取所有参数信息
        // 获取字典数据转换为MAP
        List<SysDictData> followTypeList = sysDictDataMapper.selectDictDataByType("para_category");
        List<SysDictData> followWayList = sysDictDataMapper.selectDictDataByType("input_type");
        List<SysDictData> elevatorTypeList = sysDictDataMapper.selectDictDataByType("elevator_type");
        Map<String, String> followTypeMap = followTypeList.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel, (key1, key2) -> key1));
        Map<String, String> followWayMap = followWayList.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel, (key1, key2) -> key1));
        Map<String, String> elevatorTypeMap = elevatorTypeList.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel, (key1, key2) -> key1));

        //获取所有参数转化为MAP
        List<TpParaLibrary> paraList = tpParaLibraryMapper.selectTpParaLibraryList(new TpParaLibrary());
        Map<String, String> paraMap = paraList.stream().collect(Collectors.toMap(TpParaLibrary::getParaCode, TpParaLibrary::getParaName, (key1, key2) -> key1));

        return ExcelUtils.checkData(list, it -> {
            //设置返回参数
            List<String> businessErrors = Lists.newArrayList();
            //验证空
            if (StringUtils.isEmpty(it.getParaCode())) {
                businessErrors.add("参数编码不允许为空");
            } else {
                if (it.getParaCode().length() > 60) {
                    businessErrors.add("参数编码不允许超过60个字符");
                }
            }
            if (StringUtils.isEmpty(it.getParaName())) {
                businessErrors.add("参数名称不允许为空");
            } else {
                if (it.getParaName().length() > 200) {
                    businessErrors.add("参数名称不允许超过200个字符");
                }
            }
            if (StringUtils.isEmpty(it.getParaNameUS())) {
                businessErrors.add("参数名称(英)不允许为空");
            } else {
                if (it.getParaNameUS().length() > 200) {
                    businessErrors.add("参数名称(英)不允许超过200个字符");
                }
            }

            if (StringUtils.isEmpty(it.getParaNameRU())) {
                businessErrors.add("参数名称(俄)不允许为空");
            } else {
                if (it.getParaNameRU().length() > 200) {
                    businessErrors.add("参数名称(俄)不允许超过200个字符");
                }
            }

            if (StringUtils.isEmpty(it.getParaNameES())) {
                businessErrors.add("参数名称(西)不允许为空");
            } else {
                if (it.getParaNameES().length() > 200) {
                    businessErrors.add("参数名称(西)不允许超过200个字符");
                }
            }

            if (StringUtils.isEmpty(it.getParaCategory())) {
                businessErrors.add("参数大类不允许为空");
            } else {
                if (!followTypeMap.containsKey(it.getParaCategory())) {
                    businessErrors.add("参数大类在数据字典中不存在");
                }
            }
            if (StringUtils.isEmpty(it.getInputType())) {
                businessErrors.add("输入方式不允许为空");
            } else {
                if (!followWayMap.containsKey(it.getInputType())) {
                    businessErrors.add("输入方式在数据字典中不存在");
                }
            }
            if (StringUtils.isEmpty(it.getElevatorType())) {
                businessErrors.add("电梯类型不允许为空");
            } else {
                if (!elevatorTypeMap.containsKey(it.getElevatorType())) {
                    businessErrors.add("电梯类型在数据字典中不存在");
                }
            }

            // 参数选项校验
            if ("02".equals(it.getInputType())) {
                for (ParaSelectExcel item : it.getSelectVOS()) {
                    if (StringUtils.isEmpty(item.getValue())) {
                        businessErrors.add("选项值不允许为空");
                    } else {
                        if (item.getValue().length() > 200) {
                            businessErrors.add("选项值不允许超过200个字符");
                        }
                    }
                    if (StringUtils.isEmpty(item.getLabel())) {
                        businessErrors.add("选项名称不允许为空");
                    } else {
                        if (item.getLabel().length() > 200) {
                            businessErrors.add("选项名称不允许超过200个字符");
                        }
                    }

                    if (StringUtils.isEmpty(item.getLabelUS())) {
                        businessErrors.add("选项名称(英)不允许为空");
                    } else {
                        if (item.getLabelUS().length() > 200) {
                            businessErrors.add("选项名称(英)不允许超过200个字符");
                        }
                    }

                    if (StringUtils.isEmpty(item.getLabelRU())) {
                        businessErrors.add("选项名称(俄)不允许为空");
                    } else {
                        if (item.getLabelRU().length() > 200) {
                            businessErrors.add("选项名称(俄)不允许超过200个字符");
                        }
                    }

                    if (StringUtils.isEmpty(item.getLabelES())) {
                        businessErrors.add("选项名称(西)不允许为空");
                    } else {
                        if (item.getLabelES().length() > 200) {
                            businessErrors.add("选项名称(西)不允许超过200个字符");
                        }
                    }
                }
            }
            if (StringUtils.isEmpty(it.getIsCalc())) {
                businessErrors.add("是否计算参数不允许为空");
            } else {
                if (!"0".equals(it.getIsCalc()) && !"1".equals(it.getIsCalc())) {
                    businessErrors.add("是否计算参数选项值不在范围中");
                }
            }
            if (StringUtils.isEmpty(it.getIsCivil())) {
                businessErrors.add("是否土建参数不允许为空");
            } else {
                if (!"0".equals(it.getIsCivil()) && !"1".equals(it.getIsCivil())) {
                    businessErrors.add("是否土建参数选项值不在范围中");
                }
            }
            if (StringUtils.isEmpty(it.getIsQuotation())) {
                businessErrors.add("是否报价参数不允许为空");
            } else {
                if (!"0".equals(it.getIsQuotation()) && !"1".equals(it.getIsQuotation())) {
                    businessErrors.add("是否报价参数选项值不在范围中");
                }
            }

            //验证参数编码重复
            if (businessErrors.size() == 0) {
                if (paraMap.containsKey(it.getParaCode())) {
                    businessErrors.add("参数编码已存在");
                }else if(paraMap.containsValue(it.getParaName())){
                    businessErrors.add("参数名称已存在");
                } else {
                    paraMap.put(it.getParaCode(), it.getParaName());
                }

            }

            return businessErrors;
        });
    }

    @Override
    public List<ParaLibraryExportHelper> selectTpParaLibraryListExport(TpParaLibrary tpParaLibrary) {
        List<ParaLibraryExcel> list = tpParaLibraryMapper.selectTpParaLibraryListExport2(tpParaLibrary);
        //处理数据
        List<ParaLibraryExportHelper> resList = new ArrayList<>();
        resList = resetList(list);
        return resList;
        //return tpParaLibraryMapper.selectTpParaLibraryListExport(tpParaLibrary);
    }

    @Override
    public List<ParaLibraryExportHelper> selectModelExport(TpAreaParaSelectItem tpAreaParaSelectItem) {
        List<ParaLibraryExcel> list = tpParaLibraryMapper.selectModelExport2(tpAreaParaSelectItem);
        //处理数据
        List<ParaLibraryExportHelper> resList = new ArrayList<>();
        if(ObjectUtils.isNotEmpty(list) && list.size() == 1 && ObjectUtils.isEmpty(list.get(0))){
            //特殊处理，如果只有一条数据并且为空
            //则代表没有数据,不做处理
        }else {
            resList = resetList(list);
        }
        return resList;
        //return tpParaLibraryMapper.selectModelExport(tpAreaParaSelectItem);
    }

    private List<ParaLibraryExportHelper> resetList(List<ParaLibraryExcel> list){
        //处理数据
        List<ParaLibraryExportHelper> resList = new ArrayList<>();

        for (ParaLibraryExcel item :list){
            Integer index = 1;
            ParaLibraryExportHelper main = new ParaLibraryExportHelper();
            BeanUtils.copyProperties(item,main);
            List<ParaSelectExcel> selectVOS = item.getSelectVOS();
            if(ObjectUtils.isNotEmpty(selectVOS)){
                for (ParaSelectExcel select:selectVOS){
                    ParaLibraryExportHelper others = new ParaLibraryExportHelper();
                    if(index == 1){
                        //第一个设置在main中
                        BeanUtils.copyProperties(select,main);
                        //设置选项编码
                        main.setItemCode(select.getParaCode());
                        //有可能会把paraCode覆盖所以需要重设
                        main.setParaCode(item.getParaCode());
                        resList.add(main);
                    }else {
                        BeanUtils.copyProperties(select,others);
                        others.setItemCode(select.getParaCode());
                        //有可能会把paraCode覆盖所以需要重设
                        others.setParaCode("");
                        resList.add(others);
                    }
                    index++;
                }
            }else {
                resList.add(main);
            }
        }

        return resList;
    }
}
