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

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

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.URLUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.ruoyi.common.enums.FileBuzType;
import com.ruoyi.common.exception.ServiceErrorException;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.project.business.domain.*;
import com.ruoyi.project.business.domain.vo.parabar.*;
import com.ruoyi.project.business.domain.vo.reminder.ProjectInfoVOForSendMessage;
import com.ruoyi.project.business.enums.DelFlagEnum;
import com.ruoyi.project.business.mapper.*;
import com.ruoyi.project.business.mapper.quotation.TqSpecificationDetailMapper;
import com.ruoyi.project.business.service.ITbFileService;
import com.ruoyi.project.system.domain.SysDictData;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import com.ruoyi.project.business.service.ITpParabarService;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

/**
 * 参数包Service业务层处理
 * 
 * @author ruoyi
 * @date 2024-04-28
 */
@Service
public class TpParabarServiceImpl implements ITpParabarService 
{
    @Resource
    private TpParabarMapper tpParabarMapper;

    @Resource
    private TpElevatorModelMapper tpElevatorModelMapper;

    @Resource
    private TpParabarRelatedModelMapper tpParabarRelatedModelMapper;

    @Resource
    private TpParabarDetailMapper tpParabarDetailMapper;

    @Resource
    private TpParabarDetailValueMapper tpParabarDetailValueMapper;

    @Resource
    private ITbFileService tbFileService;

    @Resource
    private TqSpecificationDetailMapper tqSpecificationDetailMapper;
    /**
     * 查询参数包
     * 
     * @param id 参数包主键
     * @return 参数包
     */
    @Override
    public TpParabar selectTpParabarById(Long id)
    {
        return tpParabarMapper.selectTpParabarById(id);
    }

    /**
     * 查询参数包列表
     * 
     * @param tpParabar 参数包
     * @return 参数包
     */
    @Override
    public List<TpParabar> selectTpParabarList(TpParabar tpParabar)
    {
        return tpParabarMapper.selectTpParabarList(tpParabar);
    }

    /**
     * 获取关联梯型
     *
     * @return 区域梯型集合
     */
    @Override
    public List<RelatedModelVO> getRelatedModelList(TpParabar tpParabar)
    {
        return tpParabarMapper.getRelatedModelList(tpParabar);
    }

    /**
     *  获取关联梯形的共同参数
     */
    public List<CommonPara> getCommonParaList(ParaForGetCommonPara para){
        List<CommonPara> returnList = new ArrayList<CommonPara>();
        returnList = tpParabarMapper.getCommonParaList(para);
        return returnList;
    }

    /**
     *  获取关联梯形的共同参数以及共同选项
     */
    public List<CommonPara> getCommonParaAndItemList(ParaForGetCommonPara para){
        List<CommonPara> returnList = new ArrayList<CommonPara>();
        returnList = tpParabarMapper.getCommonParaList(para);

        List<CommonSelectItem> selectItemList = tpParabarMapper.getCommonParaAndItemList(para);

        Long searchParaId;
        Long currentParaId;
        for(int i=0; i < returnList.size(); i++){
            searchParaId = returnList.get(i).getParaId();
            List<CommonSelectItem> tempList = new ArrayList<CommonSelectItem>();

            for(int j=0; j< selectItemList.size(); j++){
                currentParaId = selectItemList.get(j).getParaId();
                if(searchParaId.equals(currentParaId)){
                    tempList.add(selectItemList.get(j));
                }
            }
            returnList.get(i).setSelectItemList(tempList);
        }
        return returnList;
    }

    /**
     * 查询参数包配置详情
     *
     * @param parabarVO 参数包
     * @return 参数包集合
     */
    public List<ParabarDetailVO> selectParabarDetail(ParabarVO parabarVO){
        List<ParabarDetailVO>  parabarDetailList = new ArrayList<ParabarDetailVO>();

        TpParabarDetail tpParabarDetail = new TpParabarDetail();
        tpParabarDetail.setParabarId(parabarVO.getParabarId());
        List<TpParabarDetail> detailList = tpParabarDetailMapper.selectTpParabarDetailList(tpParabarDetail);
        Map<Long, List<TbFile>> fileMap = CollectionUtils.isNotEmpty(detailList) ? tbFileService.list(Wrappers.<TbFile>lambdaQuery()
                        .in(TbFile::getBusinessId, detailList.stream().map(TpParabarDetail::getId).collect(Collectors.toList()))
                        .eq(TbFile::getBusinessType, FileBuzType.PARABAR_DETAIL.getType())
                        .eq(TbFile::getDelFlag, DelFlagEnum.NORMAL.getValue()))
                .stream().collect(Collectors.groupingBy(TbFile::getBusinessId)) : Maps.newHashMap();
        for (TpParabarDetail detail :detailList) {
            ParabarDetailVO parabarDetailVO = new ParabarDetailVO();
            parabarDetailVO.setId(detail.getId());
            parabarDetailVO.setParabarDetailId(detail.getId());
            parabarDetailVO.setParabarDetailName(detail.getParabarDetailName());
            parabarDetailVO.setParabarDetailNameUS(detail.getParabarDetailNameUS());
            parabarDetailVO.setParabarDetailNameRU(detail.getParabarDetailNameRU());
            parabarDetailVO.setParabarDetailNameES(detail.getParabarDetailNameES());
            parabarDetailVO.setSortNumber(detail.getSortNumber());
            parabarDetailVO.setStatus(detail.getStatus());

            List<TbFile> files = fileMap.get(detail.getId());
            if (CollectionUtils.isNotEmpty(files)){
                parabarDetailVO.setFile(files.get(0).getFilePath());
                parabarDetailVO.setFileId(files.get(0).getId());
            }

            // 动态参数获取
            List<TpParabarDetailValue> tpParabarDetailValueList =  tpParabarDetailValueMapper.selectDetailValueByParabarDetailId(detail.getId());
            List<ParabarDetailValueVO> parabarDetailValue =  new ArrayList<ParabarDetailValueVO>();
            for (TpParabarDetailValue detailValue: tpParabarDetailValueList) {
                ParabarDetailValueVO parabarDetailValueVO = new ParabarDetailValueVO();
                parabarDetailValueVO.setParaId(detailValue.getParaId());
                parabarDetailValueVO.setParaCode(detailValue.getParaCode());
                parabarDetailValueVO.setParaValue(detailValue.getParaValue());
                parabarDetailValueVO.setParaName(detailValue.getParaName());
                parabarDetailValueVO.setParaNameUS(detailValue.getParaNameUS());
                parabarDetailValueVO.setParaNameRU(detailValue.getParaNameRU());
                parabarDetailValueVO.setParaNameES(detailValue.getParaNameES());
                parabarDetailValue.add(parabarDetailValueVO);
            }

            //  动态参数List设置
            parabarDetailVO.setParabarDetailValue(parabarDetailValue);
            parabarDetailList.add(parabarDetailVO);
        }
        return parabarDetailList;
    }

    /**
     * 新增参数包
     * 
     * @param parabarVO 参数包
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor=Exception.class)
    public int  insertTpParabar(ParabarVO parabarVO)
    {
        // 参数包参数存在check
        otherParabarUsingCheck(parabarVO);

        TpParabar tpParabar = new TpParabar();
        // 参数包表新增
        tpParabar.setParabarName(parabarVO.getParabarName());
        tpParabar.setParabarNameUS(parabarVO.getParabarNameUS());
        tpParabar.setParabarNameRU(parabarVO.getParabarNameRU());
        tpParabar.setParabarNameES(parabarVO.getParabarNameES());
        tpParabar.setDecorateFlag(parabarVO.getDecorateFlag());

        Date nowDate = DateUtils.getNowDate();
        tpParabar.setCreateBy(SecurityUtils.getUserId().toString());
        tpParabar.setCreateTime(nowDate);
        tpParabar.setUpdateBy(SecurityUtils.getUserId().toString());
        tpParabar.setUpdateTime(nowDate);
        tpParabarMapper.insertTpParabar(tpParabar);

        // 参数包关联梯型表新增
        for (Long model: parabarVO.getSelectedRrelatedModel()) {
            TpParabarRelatedModel relatedModel = new TpParabarRelatedModel();
            relatedModel.setParabarId(tpParabar.getId());
            relatedModel.setElevatorModelId(model);

            relatedModel.setCreateBy(SecurityUtils.getUserId().toString());
            relatedModel.setCreateTime(nowDate);
            relatedModel.setUpdateBy(SecurityUtils.getUserId().toString());
            relatedModel.setUpdateTime(nowDate);
            tpParabarRelatedModelMapper.insertTpParabarRelatedModel(relatedModel);
        }

        // 参数包配置表新增
        for (ParabarDetailVO detail: parabarVO.getParabarDetail()) {
            TpParabarDetail tpParabarDetail = new TpParabarDetail();
            tpParabarDetail.setParabarId(tpParabar.getId());
            tpParabarDetail.setParabarDetailName(detail.getParabarDetailName());
            tpParabarDetail.setParabarDetailNameUS(detail.getParabarDetailNameUS());
            tpParabarDetail.setParabarDetailNameRU(detail.getParabarDetailNameRU());
            tpParabarDetail.setParabarDetailNameES(detail.getParabarDetailNameES());
            tpParabarDetail.setSortNumber(detail.getSortNumber());
            tpParabarDetail.setStatus(detail.getStatus());
            tpParabarDetail.setFile(detail.getFile());

            tpParabarDetail.setCreateBy(SecurityUtils.getUserId().toString());
            tpParabarDetail.setCreateTime(nowDate);
            tpParabarDetail.setUpdateBy(SecurityUtils.getUserId().toString());
            tpParabarDetail.setUpdateTime(nowDate);
            tpParabarDetailMapper.insertTpParabarDetail(tpParabarDetail);

            // 保存参数包图片
            saveParabarDetailFile(tpParabarDetail);

            for (ParabarDetailValueVO detailValue: detail.getParabarDetailValue()) {
                TpParabarDetailValue tpParabarDetailValue = new TpParabarDetailValue();
                tpParabarDetailValue.setParabarId(tpParabar.getId());
                tpParabarDetailValue.setParabarDetailId(tpParabarDetail.getId());
                tpParabarDetailValue.setParaCode(detailValue.getParaCode());
                tpParabarDetailValue.setParaValue(detailValue.getParaValue());

                tpParabarDetailValue.setCreateBy(SecurityUtils.getUserId().toString());
                tpParabarDetailValue.setCreateTime(nowDate);
                tpParabarDetailValue.setUpdateBy(SecurityUtils.getUserId().toString());
                tpParabarDetailValue.setUpdateTime(nowDate);
                tpParabarDetailValueMapper.insertTpParabarDetailValue(tpParabarDetailValue);
            }
        }

        return 1;
    }

    /**
     * 修改参数包
     * 
     * @param parabarVO 参数包
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateTpParabar(ParabarVO parabarVO)
    {
        // 参数包关联梯型表先删除再新增
        tpParabarRelatedModelMapper.deleteTpParabarRelatedModelByParabarId(parabarVO.getParabarId());
        tpParabarDetailValueMapper.deleteTpParabarDetailValueByParabarId(parabarVO.getParabarId());

        // 参数包参数存在check
        otherParabarUsingCheck(parabarVO);

        TpParabar tpParabar = new TpParabar();
        // 参数包表编辑
        tpParabar.setId(parabarVO.getParabarId());
        tpParabar.setParabarName(parabarVO.getParabarName());
        tpParabar.setParabarNameUS(parabarVO.getParabarNameUS());
        tpParabar.setParabarNameRU(parabarVO.getParabarNameRU());
        tpParabar.setParabarNameES(parabarVO.getParabarNameES());
        tpParabar.setDecorateFlag(parabarVO.getDecorateFlag());

        Date nowDate = DateUtils.getNowDate();
        tpParabar.setUpdateBy(SecurityUtils.getUserId().toString());
        tpParabar.setUpdateTime(nowDate);
        tpParabarMapper.updateTpParabar(tpParabar);

        for (Long model: parabarVO.getSelectedRrelatedModel()){
            TpParabarRelatedModel relatedModel = new TpParabarRelatedModel();
            relatedModel.setParabarId(parabarVO.getParabarId());
            relatedModel.setElevatorModelId(model);

            relatedModel.setCreateBy(SecurityUtils.getUserId().toString());
            relatedModel.setCreateTime(nowDate);
            relatedModel.setUpdateBy(SecurityUtils.getUserId().toString());
            relatedModel.setUpdateTime(nowDate);
            tpParabarRelatedModelMapper.insertTpParabarRelatedModel(relatedModel);
        }


        // 参数包明细不能删除后重插，不然会导致已选内容无法回显
        for (ParabarDetailVO detail: parabarVO.getParabarDetail()) {
            TpParabarDetail tpParabarDetail = new TpParabarDetail();
            tpParabarDetail.setId(detail.getId());
            tpParabarDetail.setParabarId(parabarVO.getParabarId());
            tpParabarDetail.setParabarDetailName(detail.getParabarDetailName());
            tpParabarDetail.setParabarDetailNameUS(detail.getParabarDetailNameUS());
            tpParabarDetail.setParabarDetailNameRU(detail.getParabarDetailNameRU());
            tpParabarDetail.setParabarDetailNameES(detail.getParabarDetailNameES());
            tpParabarDetail.setSortNumber(detail.getSortNumber());
            tpParabarDetail.setStatus(detail.getStatus());
            tpParabarDetail.setFile(detail.getFile());
            tpParabarDetail.setCreateBy(SecurityUtils.getUserId().toString());
            tpParabarDetail.setCreateTime(nowDate);
            tpParabarDetail.setUpdateBy(SecurityUtils.getUserId().toString());
            tpParabarDetail.setUpdateTime(nowDate);

            // 处理新增及修改的数据
            if (Objects.isNull(tpParabarDetail.getId())){
                tpParabarDetailMapper.insertTpParabarDetail(tpParabarDetail);
            } else {
                tpParabarDetailMapper.updateById(tpParabarDetail);
            }

            // 删除该配置的URL
            if(detail.getFileId() != null && detail.getFileId() > 0){
                tbFileService.deleteTbFileById(detail.getFileId());
            }
            // 保存参数包图片
            saveParabarDetailFile(tpParabarDetail);
            for (ParabarDetailValueVO detailValue: detail.getParabarDetailValue()) {
                TpParabarDetailValue tpParabarDetailValue = new TpParabarDetailValue();
                tpParabarDetailValue.setParabarId(parabarVO.getParabarId());
                tpParabarDetailValue.setParabarDetailId(tpParabarDetail.getId());
                tpParabarDetailValue.setParaCode(detailValue.getParaCode());
                tpParabarDetailValue.setParaValue(detailValue.getParaValue());

                tpParabarDetailValue.setCreateBy(SecurityUtils.getUserId().toString());
                tpParabarDetailValue.setCreateTime(nowDate);
                tpParabarDetailValue.setUpdateBy(SecurityUtils.getUserId().toString());
                tpParabarDetailValue.setUpdateTime(nowDate);
                tpParabarDetailValueMapper.insertTpParabarDetailValue(tpParabarDetailValue);
            }
        }

        return 1;
    }

    private void otherParabarUsingCheck(ParabarVO parabarVO) {
        List<ParabarDetailVO> detailList = parabarVO.getParabarDetail();
        if(detailList == null || detailList.size() == 0){
            throw new ServiceException("配置列表至少添加一个配置行");
        }
        List<ParabarDetailValueVO> paraList = detailList.get(0).getParabarDetailValue();
        if(paraList == null || paraList.size() == 0){
            throw new ServiceException("参数包中至少添加一个参数");
        }

        ParaModelRelatedVO paramVO = new ParaModelRelatedVO();
        paramVO.setModelIds(parabarVO.getSelectedRrelatedModel());

        List<ParaModelRelatedVO> paraModelRelatedList = tpParabarMapper.selectParaModelRelatedList(paramVO);
        Map<Long, Map<String, String>> modelParaMap = new HashMap<Long, Map<String, String>>();
        saveIntoMap(modelParaMap, paraModelRelatedList);

        Map<String, String> paraMap =  new HashMap<String, String>();
        for (Long modelId: paramVO.getModelIds()) {
            if(modelParaMap.containsKey(modelId)){
                paraMap = modelParaMap.get(modelId);
                for (ParabarDetailValueVO para : paraList) {
                    if(paraMap.containsKey(para.getParaCode())){
                        throw new ServiceException("列表中添加的参数 [" + paraMap.get(para.getParaCode())+ "]，正在使用的其他参数包中存在" );
                    }
                }
            }

        }

        if (Objects.isNull(parabarVO.getParabarId())){
            return;
        }
        // 使用中的参数不能删除
        TpParabarDetail paraDetail = new TpParabarDetail();
        paraDetail.setParabarId(parabarVO.getParabarId());
        List<Long> existDetails = tpParabarDetailMapper.selectTpParabarDetailList(paraDetail)
                .stream().map(TpParabarDetail::getId).collect(Collectors.toList());
        List<Long> remainedDetails = CollectionUtils.isNotEmpty(parabarVO.getParabarDetail()) ?
                parabarVO.getParabarDetail().stream().map(ParabarDetailVO::getId).collect(Collectors.toList()): new ArrayList<>();
        // 获得需要删除的明细
        existDetails.removeAll(remainedDetails);
        List<Long> usingDetails = tqSpecificationDetailMapper.getUsingDetails();
        List<Long> removeIds = Lists.newArrayList(existDetails);
        // 获得删除明细中还在使用的
        existDetails.retainAll(usingDetails);
        if (CollectionUtils.isNotEmpty(existDetails)){
            throw new ServiceException("正在使用中的配置不能删除");
        }
        if (CollectionUtils.isNotEmpty(removeIds)){
            tpParabarDetailMapper.deleteTpParabarDetailByIds(removeIds.toArray(new Long[]{}));
        }

    }


    private void saveParabarDetailFile(TpParabarDetail tpParabarDetail) {
        // 保存附件
        String file = tpParabarDetail.getFile();
        if (StringUtils.isNotBlank(file)) {
            for (String fileUrl : file.split(",")) {
                // 获取文件名：
                // 解析URL
                String path = URLUtil.getPath(fileUrl);
                // 从路径中获取文件名
                String fileName = FileUtil.getName(path);
                TbFile tbFile = new TbFile(tpParabarDetail.getId(), FileBuzType.PARABAR_DETAIL.getType(), fileName, fileName, fileUrl);
                tbFile.setCreateBy(SecurityUtils.getUserId().toString());
                tbFile.setCreateTime(new Date());
                tbFileService.insertTbFile(tbFile);
            }
        }
    }

    private void saveIntoMap(Map<Long, Map<String, String>> modelParaMap, List<ParaModelRelatedVO> paraModelRelatedList){

        for(int i=0;i<paraModelRelatedList.size();i++){
            if(modelParaMap.containsKey(paraModelRelatedList.get(i).getElevatorModelId())){
                Map<String, String> oldMap = modelParaMap.get(paraModelRelatedList.get(i).getElevatorModelId());
                if(!oldMap.containsKey(paraModelRelatedList.get(i).getParaCode())){
                    oldMap.put(paraModelRelatedList.get(i).getParaCode(), paraModelRelatedList.get(i).getParaName());
                }
                modelParaMap.put(paraModelRelatedList.get(i).getElevatorModelId(), oldMap);
            }else{
                Map<String, String> newMap =  new HashMap<String, String>();
                newMap.put(paraModelRelatedList.get(i).getParaCode(), paraModelRelatedList.get(i).getParaName());
                modelParaMap.put(paraModelRelatedList.get(i).getElevatorModelId(), newMap);
            }
        }
    }

    /**
     * 批量删除参数包
     * 
     * @param ids 需要删除的参数包主键
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteTpParabarByIds(Long[] ids)
    {
        Arrays.stream(ids).forEach(id -> {
            TpParabar sqlData = tpParabarMapper.selectTpParabarById(id);
            if (sqlData == null || DelFlagEnum.DELETED.getValue().equals(sqlData.getDelFlag())) {
                //数据已被删除
                throw new ServiceErrorException(MessageUtils.message("common.dataDeleted"));
            }
        });

        // 使用中的不能删除
        TpParabarRelatedModel param = new TpParabarRelatedModel();
        param.setParabarIds(Lists.newArrayList(ids));
        if (tpParabarRelatedModelMapper.checkRelated(param)){
            throw new ServiceException("参数包已被报价使用，无法删除");
        }

        tpParabarMapper.deleteTpParabarByIds(ids);
        tpParabarRelatedModelMapper.softDeleteTpParabarRelatedModelByParabarId(ids);
        tpParabarDetailMapper.softDeleteTpParabarDetailByParabarId(ids);
        tpParabarDetailValueMapper.softDeleteTpParabarDetailValueByParabarId(ids);
        return 1;
    }

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

    /**
     * 修改参数状态
     *
     * @param tpParabar 参数
     * @return 结果
     */
    @Override
    public int updateParaStatus(TpParabar tpParabar) {
        return tpParabarMapper.updateTpParabar(tpParabar);
    }

    @Override
    public List<ElParabarVO> getParabarConfigByElevatorModelId(Long id) {
        return tpParabarMapper.getParabarConfigByElevatorModelId(id);
    }
}
