package com.xisc.pm.app.service.impl;

import com.xisc.pm.api.dto.export.PmPlateSpecBtDTO;
import com.xisc.pm.app.service.PmPlateSpecBtService;
import com.xisc.pm.domain.entity.PmPlateSpecBt;
import com.xisc.pm.domain.entity.PmPlateSpecBtTra;
import com.xisc.pm.domain.repository.PmPlateSpecBtRepository;
import com.xisc.pm.domain.repository.PmPlateSpecBtTraRepository;
import com.xisc.pm.infra.constant.Constants;
import com.xisc.pm.infra.util.BeanUtils;
import com.xisc.pm.infra.util.Utils;
import io.choerodon.core.domain.Page;
import io.choerodon.core.exception.CommonException;
import io.choerodon.core.oauth.DetailsHelper;
import io.choerodon.mybatis.pagehelper.PageHelper;
import io.choerodon.mybatis.pagehelper.domain.PageRequest;
import org.apache.commons.collections.CollectionUtils;
import org.hzero.boot.platform.lov.adapter.LovAdapter;
import org.hzero.boot.platform.lov.dto.LovValueDTO;
import org.hzero.mybatis.domian.Condition;
import org.hzero.mybatis.util.Sqls;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

/**
 * 钢板轧制规格基准表(PmPlateSpecBt)应用服务
 *
 * @author 蒋雨航 yuhang.jiang02@hand-china.com
 * @since 2024-09-05 14:45:54
 */
@Service
public class PmPlateSpecBtServiceImpl implements PmPlateSpecBtService {
    @Autowired
    private PmPlateSpecBtRepository pmPlateSpecBtRepository;

    @Autowired
    private PmPlateSpecBtTraRepository pmPlateSpecBtTraRepository;

    @Autowired
    private LovAdapter lovAdapter;

    @Override
    public Page<PmPlateSpecBt> selectList(PageRequest pageRequest, PmPlateSpecBt pmPlateSpecBt) {
        return PageHelper.doPageAndSort(pageRequest, () -> pmPlateSpecBtRepository.selectList(pmPlateSpecBt));
    }

    @Override
    public void saveData(List<PmPlateSpecBt> pmPlateSpecBts) {
        // 检查数据列表是否为空，如果为空则直接返回
        if (CollectionUtils.isEmpty(pmPlateSpecBts)) {
            return;
        }
        Long tenantId = pmPlateSpecBts.get(0).getTenantId();
        for (PmPlateSpecBt pmPlateSpecBt : pmPlateSpecBts) {
            //单条记录中，“钢板厚度起”必须小于“钢板厚度止”；
            if (pmPlateSpecBt.getPlateThickFrom().compareTo(pmPlateSpecBt.getPlateThickTo()) >= 0) {
                throw new CommonException("pm.plate_spec_bt_001", pmPlateSpecBt.getPlateThickFrom(), pmPlateSpecBt.getPlateThickTo());
            }
            //单条记录中，“组合板宽度起”必须小于“组合板宽度止
            if (pmPlateSpecBt.getCombinePlateWidthFrom().compareTo(pmPlateSpecBt.getCombinePlateWidthTo()) >= 0) {
                throw new CommonException("pm.plate_spec_bt_002", pmPlateSpecBt.getCombinePlateWidthFrom(), pmPlateSpecBt.getCombinePlateWidthTo());
            }
        }
        // 新增记录之间校验区间是否交叉
        // 校验钢板厚度
        Map<String, List<PmPlateSpecBt>> slabThickBtMap = pmPlateSpecBts.stream().collect(Collectors.groupingBy(this::getSlabKey));
        for (Map.Entry<String, List<PmPlateSpecBt>> entry : slabThickBtMap.entrySet()) {
            List<PmPlateSpecBt> list = entry.getValue();
            for (int i = 0; i < list.size() - 1; i++) {
                for (int j = i + 1; j < list.size(); j++) {
                    // 校验钢板厚度区间是否交叉
                    boolean slabThickIntervalCheck = Utils.isIntersect(list.get(i).getPlateThickFrom(), list.get(i).getPlateThickTo(),
                            list.get(j).getPlateThickFrom(), list.get(j).getPlateThickTo());
                    if (!slabThickIntervalCheck) {
                        continue;
                    }

                    // 校验组合板宽度区间是否交叉
                    boolean slabWidthIntervalCheck = Utils.isIntersect(list.get(i).getCombinePlateWidthFrom(), list.get(i).getCombinePlateWidthTo(),
                            list.get(j).getCombinePlateWidthFrom(), list.get(j).getCombinePlateWidthTo());
                    if (!slabWidthIntervalCheck) {
                        continue;
                    }

                    throw new CommonException("pm.thick_addv_bt_003", list.get(j).getPlateThickFrom(), list.get(j).getPlateThickTo(),
                            list.get(j).getCombinePlateWidthFrom(), list.get(j).getCombinePlateWidthTo());
                }
            }
        }

        // 获取字段集合，查询数据库该范围内数据
        List<String> stCodeList = pmPlateSpecBts.stream().map(PmPlateSpecBt::getStCode).collect(Collectors.toList());
        List<String> formPlateModeList = pmPlateSpecBts.stream().map(PmPlateSpecBt::getFormPlateMode).collect(Collectors.toList());
        List<String> adTypeModeList = pmPlateSpecBts.stream().map(PmPlateSpecBt::getAdTypeMode).collect(Collectors.toList());
        List<String> rollModeList = pmPlateSpecBts.stream().map(PmPlateSpecBt::getRollMode).collect(Collectors.toList());
        List<String> wholeHeatTreatmentTypeList = pmPlateSpecBts.stream().map(PmPlateSpecBt::getWholeHeatTreatmentType).collect(Collectors.toList());
        List<String> rollLineNoList = pmPlateSpecBts.stream().map(PmPlateSpecBt::getRollLineNo).collect(Collectors.toList());
        List<Long> idList = pmPlateSpecBts.stream().filter(item -> item.getPptabId() != null).map(PmPlateSpecBt::getPptabId).collect(Collectors.toList());
        List<PmPlateSpecBt> existList = pmPlateSpecBtRepository.selectByCondition(Condition.builder(PmPlateSpecBt.class)
                .andWhere(Sqls.custom().andEqualTo(PmPlateSpecBt.FIELD_TENANT_ID, tenantId))
                .andWhere(Sqls.custom().andIn(PmPlateSpecBt.FIELD_ST_CODE, stCodeList))
                .andWhere(Sqls.custom().andIn(PmPlateSpecBt.FIELD_FORM_PLATE_MODE, formPlateModeList))
                .andWhere(Sqls.custom().andIn(PmPlateSpecBt.FIELD_AD_TYPE_MODE, adTypeModeList))
                .andWhere(Sqls.custom().andIn(PmPlateSpecBt.FIELD_ROLL_MODE, rollModeList))
                .andWhere(Sqls.custom().andIn(PmPlateSpecBt.FIELD_WHOLE_HEAT_TREATMENT_TYPE, wholeHeatTreatmentTypeList))
                .andWhere(Sqls.custom().andIn(PmPlateSpecBt.FIELD_ROLL_LINE_NO, rollLineNoList))
                .andWhere(Sqls.custom().andNotIn(PmPlateSpecBt.FIELD_PPTAB_ID, idList, true))
                .build());

        // 与数据库记录校验区间是否交叉
        if (CollectionUtils.isNotEmpty(existList)) {
            // 校验板坯厚度
            Map<String, List<PmPlateSpecBt>> existSlabBtMap = existList.stream().collect(Collectors.groupingBy(this::getSlabKey));

            for (PmPlateSpecBt slabSpecBt : pmPlateSpecBts) {
                if (existSlabBtMap.containsKey(getSlabKey(slabSpecBt))) {
                    List<PmPlateSpecBt> slabSpecBtValueList = existSlabBtMap.get(getSlabKey(slabSpecBt));
                    for (PmPlateSpecBt specBt : slabSpecBtValueList) {
                        // 校验钢板厚度区间是否交叉
                        boolean slabThickIntervalCheck = Utils.isIntersect(slabSpecBt.getPlateThickFrom()
                                , slabSpecBt.getPlateThickTo(), specBt.getPlateThickFrom(), specBt.getPlateThickTo());
                        if (!slabThickIntervalCheck) {
                            continue;
                        }

                        // 校验组合板宽度区间是否交叉
                        boolean slabWidthIntervalCheck = Utils.isIntersect(slabSpecBt.getCombinePlateWidthFrom()
                                , slabSpecBt.getCombinePlateWidthTo(), specBt.getCombinePlateWidthFrom(), specBt.getCombinePlateWidthTo());
                        if (!slabWidthIntervalCheck) {
                            continue;
                        }

                        throw new CommonException("pm.thick_addv_bt_004",specBt.getPlateThickFrom(), specBt.getPlateThickTo(),
                                specBt.getCombinePlateWidthFrom(), specBt.getCombinePlateWidthTo());
                    }
                }
            }
        }

        // 分别筛选出待新增和待更新的
        List<PmPlateSpecBt> insertList = pmPlateSpecBts.stream().filter(line -> line.getPptabId() == null).collect(Collectors.toList());
        List<PmPlateSpecBt> updateList = pmPlateSpecBts.stream().filter(line -> line.getPptabId() != null).collect(Collectors.toList());

        // 获取当前时间和用户信息。
        Date now = new Date();
        String username = DetailsHelper.getUserDetails().getUsername();
        List<PmPlateSpecBtTra> insertPmMoldSpecBtTraList = new ArrayList<>(pmPlateSpecBts.size());
        // 记录历史表
        for (PmPlateSpecBt item : updateList) {
            PmPlateSpecBtTra pmPlateSpecBtTra = new PmPlateSpecBtTra();
            BeanUtils.copy(item, pmPlateSpecBtTra);

            // 设置操作类型为更新（U），并记录操作时间和用户
            pmPlateSpecBtTra.setOperationType("U");
            pmPlateSpecBtTra.setOperationTime(now);
            pmPlateSpecBtTra.setOperationUser(username);
            insertPmMoldSpecBtTraList.add(pmPlateSpecBtTra);

        }
        pmPlateSpecBtRepository.batchInsertSelective(insertList);
        pmPlateSpecBtRepository.batchUpdateByPrimaryKey(updateList);

        for (PmPlateSpecBt pmMoldSpecBt : insertList) {
            PmPlateSpecBtTra pmPlateSpecBtTra = new PmPlateSpecBtTra();
            BeanUtils.copy(pmMoldSpecBt, pmPlateSpecBtTra);

            // 设置操作类型为插入（I），并记录操作时间和用户
            pmPlateSpecBtTra.setOperationType("I");
            pmPlateSpecBtTra.setOperationTime(now);
            pmPlateSpecBtTra.setOperationUser(username);
            insertPmMoldSpecBtTraList.add(pmPlateSpecBtTra);

        }
        // 插入保存或者更新记录到对应履历表
        pmPlateSpecBtTraRepository.batchInsertSelective(insertPmMoldSpecBtTraList);
    }

    @Override
    public List<PmPlateSpecBtDTO> exportList(PmPlateSpecBt pmPlateSpecBt) {
        if ("*" .equals(pmPlateSpecBt.getAdTypeMode())) {
            pmPlateSpecBt.setAdTypeMode(null);
        }
        if ("*" .equals(pmPlateSpecBt.getWholeHeatTreatmentType())) {
            pmPlateSpecBt.setWholeHeatTreatmentType(null);
        }
        if ("*" .equals(pmPlateSpecBt.getRollMode())) {
            pmPlateSpecBt.setRollMode(null);
        }
        List<PmPlateSpecBt> list = pmPlateSpecBtRepository.selectList(pmPlateSpecBt);
        // 如果集合为空，则返回
        if (CollectionUtils.isEmpty(list)) {
            return Collections.emptyList();
        }
        // 组板方式
        List<LovValueDTO> formPlateModeList = lovAdapter.queryLovValue(Constants.LovCode.FORM_PLATE_MODE_FIRST, pmPlateSpecBt.getTenantId());
        Map<String, String> formPlateModeMap = new HashMap<>(formPlateModeList.size());
        if (CollectionUtils.isNotEmpty(formPlateModeList)) {
            formPlateModeMap = formPlateModeList.stream().collect(Collectors.toMap(LovValueDTO::getValue, LovValueDTO::getMeaning));
        }
        // AD模式
        List<LovValueDTO> adTypeModeList = lovAdapter.queryLovValue(Constants.LovCode.BT_AD_TYPE_MODE, pmPlateSpecBt.getTenantId());
        Map<String, String> adTypeModeMap = new HashMap<>(adTypeModeList.size());
        if (CollectionUtils.isNotEmpty(formPlateModeList)) {
            adTypeModeMap = adTypeModeList.stream().collect(Collectors.toMap(LovValueDTO::getValue, LovValueDTO::getMeaning));
        }
        // 轧制模式
        List<LovValueDTO> rollModeList = lovAdapter.queryLovValue(Constants.LovCode.BT_ROLL_MODE, pmPlateSpecBt.getTenantId());
        Map<String, String> rollModeListLovMap = new HashMap<>(rollModeList.size());
        if (CollectionUtils.isNotEmpty(rollModeList)) {
            rollModeListLovMap = rollModeList.stream().collect(Collectors.toMap(LovValueDTO::getValue, LovValueDTO::getMeaning));
        }
        // 热处理
        List<LovValueDTO> heatTreatModeList = lovAdapter.queryLovValue(Constants.LovCode.BT_HEAT_TREAT_MODE, pmPlateSpecBt.getTenantId());
        Map<String, String> heatTreatModeMap = new HashMap<>(heatTreatModeList.size());
        if (CollectionUtils.isNotEmpty(heatTreatModeList)) {
            heatTreatModeMap = heatTreatModeList.stream().collect(Collectors.toMap(LovValueDTO::getValue, LovValueDTO::getMeaning));
        }
        // 轧制产线号含义
        List<LovValueDTO> rollLineNoList = lovAdapter.queryLovValue(Constants.LovCode.ROLL_LINE_NO, pmPlateSpecBt.getTenantId());
        Map<String, String> rollLineNoLovMap = new HashMap<>(rollLineNoList.size());
        if (CollectionUtils.isNotEmpty(rollLineNoList)) {
            rollLineNoLovMap = rollLineNoList.stream().collect(Collectors.toMap(LovValueDTO::getValue, LovValueDTO::getMeaning));
        }

        List<PmPlateSpecBtDTO> resultList = new ArrayList<>();
        for (PmPlateSpecBt line : list) {
            if (!rollLineNoLovMap.isEmpty()) {
                line.setRollLineNoDesc(rollLineNoLovMap.getOrDefault(line.getRollLineNo(), ""));
            }
            PmPlateSpecBtDTO pmPlateSpecBtDTO = new PmPlateSpecBtDTO();
            BeanUtils.copy(line, pmPlateSpecBtDTO);
            if (!formPlateModeMap.isEmpty()) {
                pmPlateSpecBtDTO.setFormPlateModeDesc(formPlateModeMap.getOrDefault(line.getFormPlateMode(), ""));
            }
            if (!adTypeModeMap.isEmpty()) {
                pmPlateSpecBtDTO.setAdTypeModeDesc(adTypeModeMap.getOrDefault(line.getAdTypeMode(), ""));
            }
            if (!rollModeListLovMap.isEmpty()) {
                pmPlateSpecBtDTO.setRollModeDesc(rollModeListLovMap.getOrDefault(line.getRollMode(), ""));
            }
            if (!heatTreatModeMap.isEmpty()) {
                pmPlateSpecBtDTO.setWholeHeatTreatmentTypeDesc(heatTreatModeMap.getOrDefault(line.getWholeHeatTreatmentType(), ""));
            }
            resultList.add(pmPlateSpecBtDTO);
        }
        return resultList;
    }

    @Override
    public String getSlabKey(PmPlateSpecBt plateSpecBt) {
        return plateSpecBt.getStCode() + "-" + plateSpecBt.getFormPlateMode() + "-" + plateSpecBt.getAdTypeMode() + "-" +
                plateSpecBt.getRollMode() + "-" + plateSpecBt.getWholeHeatTreatmentType() + "-" + plateSpecBt.getRollLineNo();
    }

}

