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

import com.xisc.pm.api.dto.export.PmThickAddvBtDTO;
import com.xisc.pm.app.service.PmThickAddvBtService;
import com.xisc.pm.domain.entity.PmThickAddvBt;
import com.xisc.pm.domain.entity.PmThickAddvBtTra;
import com.xisc.pm.domain.repository.PmThickAddvBtRepository;
import com.xisc.pm.domain.repository.PmThickAddvBtTraRepository;
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 org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 钢板厚度余量基准表(PmThickAddvBt)应用服务
 *
 * @author 蒋雨航 yuhang.jiang02@hand-china.com
 * @since 2024-09-05 15:04:57
 */
@Service
public class PmThickAddvBtServiceImpl implements PmThickAddvBtService {
    @Autowired
    private PmThickAddvBtRepository pmThickAddvBtRepository;

    @Autowired
    private PmThickAddvBtTraRepository pmThickAddvBtTraRepository;

    @Autowired
    private LovAdapter lovAdapter;

    @Override
    public Page<PmThickAddvBt> selectList(PageRequest pageRequest, PmThickAddvBt pmThickAddvBt) {
        return PageHelper.doPageAndSort(pageRequest, () -> pmThickAddvBtRepository.selectList(pmThickAddvBt));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void saveData(List<PmThickAddvBt> pmThickAddvBts) {
        // 检查数据列表是否为空，如果为空则直接返回
        if (CollectionUtils.isEmpty(pmThickAddvBts)) {
            return;
        }
        Long tenantId = pmThickAddvBts.get(0).getTenantId();
        for (PmThickAddvBt pmThickAddvBt : pmThickAddvBts) {
            //单条记录中，“钢板厚度起”必须小于“钢板厚度止”；
            if (pmThickAddvBt.getPlateThickFrom().compareTo(pmThickAddvBt.getPlateThickTo()) >= 0) {
                throw new CommonException("pm.thick_addv_bt_001", pmThickAddvBt.getPlateThickFrom(), pmThickAddvBt.getPlateThickTo());
            }
            //单条记录中，“组合板宽度起”必须小于“组合板宽度止
            if (pmThickAddvBt.getCombinePlateWidthFrom().compareTo(pmThickAddvBt.getCombinePlateWidthTo()) >= 0) {
                throw new CommonException("pm.thick_addv_bt_002", pmThickAddvBt.getCombinePlateWidthFrom(), pmThickAddvBt.getCombinePlateWidthTo());
            }
        }

        // 新增记录之间校验区间是否交叉
        // 校验钢板厚度
        Map<String, List<PmThickAddvBt>> slabThickBtMap = pmThickAddvBts.stream().collect(Collectors.groupingBy(this::getPlateKey));
        for (Map.Entry<String, List<PmThickAddvBt>> entry : slabThickBtMap.entrySet()) {
            List<PmThickAddvBt> 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> toleTypeList = pmThickAddvBts.stream().map(PmThickAddvBt::getTolTypeCode).collect(Collectors.toList());
        List<String> wholeHeatTreatmentTypeList = pmThickAddvBts.stream().map(PmThickAddvBt::getWholeHeatTreatmentType).collect(Collectors.toList());
        List<String> mscLineNoList = pmThickAddvBts.stream().map(PmThickAddvBt::getMscLineNo).collect(Collectors.toList());
        List<BigDecimal> thickAddvList = pmThickAddvBts.stream().map(PmThickAddvBt::getThickAddv).collect(Collectors.toList());
        List<Long> idList = pmThickAddvBts.stream().filter(pmThickAddvBt -> pmThickAddvBt.getPptabId() != null).map(PmThickAddvBt::getPptabId).collect(Collectors.toList());
        List<PmThickAddvBt> existList = pmThickAddvBtRepository.selectByCondition(Condition.builder(PmThickAddvBt.class)
                .andWhere(Sqls.custom().andEqualTo(PmThickAddvBt.FIELD_TENANT_ID, tenantId))
                .andWhere(Sqls.custom().andIn(PmThickAddvBt.FIELD_TOL_TYPE_CODE, toleTypeList))
                .andWhere(Sqls.custom().andIn(PmThickAddvBt.FIELD_WHOLE_HEAT_TREATMENT_TYPE, wholeHeatTreatmentTypeList))
                .andWhere(Sqls.custom().andIn(PmThickAddvBt.FIELD_MSC_LINE_NO, mscLineNoList))
                .andWhere(Sqls.custom().andIn(PmThickAddvBt.FIELD_THICK_ADDV, thickAddvList))
                .andWhere(Sqls.custom().andNotIn(PmThickAddvBt.FIELD_PPTAB_ID, idList, true))
                .build());

        // 与数据库记录校验区间是否交叉
        if (CollectionUtils.isNotEmpty(existList)) {
            // 校验
            Map<String, List<PmThickAddvBt>> existSlabBtMap = existList.stream().collect(Collectors.groupingBy(this::getPlateKey));
            for (PmThickAddvBt slabSpecBt : pmThickAddvBts) {
                if (existSlabBtMap.containsKey(getPlateKey(slabSpecBt))) {
                    List<PmThickAddvBt> slabSpecBtValueList = existSlabBtMap.get(getPlateKey(slabSpecBt));
                    for (PmThickAddvBt 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<PmThickAddvBt> insertList = pmThickAddvBts.stream().filter(line -> line.getPptabId() == null).collect(Collectors.toList());
        List<PmThickAddvBt> updateList = pmThickAddvBts.stream().filter(line -> line.getPptabId() != null).collect(Collectors.toList());

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

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

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

        for (PmThickAddvBt pmMoldSpecBt : insertList) {
            PmThickAddvBtTra pmThickAddBtTra = new PmThickAddvBtTra();
            BeanUtils.copy(pmMoldSpecBt, pmThickAddBtTra);

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

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

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteForUi(List<PmThickAddvBt> pmThickAddvBtList) {
        if (CollectionUtils.isNotEmpty(pmThickAddvBtList)) {
            // 删除
            pmThickAddvBtRepository.batchDeleteByPrimaryKey(pmThickAddvBtList);

            // 记录历史表
            Date now = new Date();
            String username = DetailsHelper.getUserDetails().getUsername();
            List<PmThickAddvBtTra> insertPmThickAddvBtTraList = new ArrayList<>(pmThickAddvBtList.size());
            for (PmThickAddvBt pmThickAddvBt : pmThickAddvBtList) {
                PmThickAddvBtTra pmThickAddvBtTra = new PmThickAddvBtTra();

                // 设置操作类型为删除（D），并记录操作时间和服务用户。
                org.springframework.beans.BeanUtils.copyProperties(pmThickAddvBt, pmThickAddvBtTra);
                pmThickAddvBtTra.setOperationType("D");
                pmThickAddvBtTra.setOperationTime(now);
                pmThickAddvBtTra.setOperationUser(username);
                insertPmThickAddvBtTraList.add(pmThickAddvBtTra);

            }
            // 插入删除记录到对应履历表
            pmThickAddvBtTraRepository.batchInsertSelective(insertPmThickAddvBtTraList);
        }
    }

    @Override
    public String getPlateKey(PmThickAddvBt pmThickAddvBt) {
        return pmThickAddvBt.getTolTypeCode() + "-" + pmThickAddvBt.getWholeHeatTreatmentType() + "-" + pmThickAddvBt.getMscLineNo();
    }

    @Override
    public List<PmThickAddvBtDTO> exportList(Long tenantId, PmThickAddvBt pmThickAddvBt) {
        List<PmThickAddvBtDTO> resultList = new ArrayList<>();
        List<PmThickAddvBt> pmThickAddvBtList = pmThickAddvBtRepository.selectList(pmThickAddvBt);
        if (CollectionUtils.isNotEmpty(pmThickAddvBtList)) {
            // 获取热处理类型含义
            List<LovValueDTO> treatModeList = lovAdapter.queryLovValue(Constants.LovCode.BT_HEAT_TREAT_MODE, tenantId);
            Map<String, String> treatModeMap = new HashMap<>(treatModeList.size());
            if (CollectionUtils.isNotEmpty(treatModeList)) {
                treatModeMap = treatModeList.stream().collect(Collectors.toMap(LovValueDTO::getValue, LovValueDTO::getMeaning));
            }
            // 获取产线号含义
            List<LovValueDTO> mscLineNoList = lovAdapter.queryLovValue(Constants.LovCode.MSC_LINE_NO, tenantId);
            Map<String, String> mscLineNoMap = new HashMap<>(mscLineNoList.size());
            if (CollectionUtils.isNotEmpty(mscLineNoList)) {
                mscLineNoMap = mscLineNoList.stream().collect(Collectors.toMap(LovValueDTO::getValue, LovValueDTO::getMeaning));
            }

            // 获取公差类型代码
            List<LovValueDTO> typeCodeList = lovAdapter.queryLovValue(Constants.LovCode.TM_CROSS_CODE, tenantId);
            Map<String, String> typeCodeMap = new HashMap<>(typeCodeList.size());
            if (CollectionUtils.isNotEmpty(typeCodeList)) {
                typeCodeMap = typeCodeList.stream().collect(Collectors.toMap(LovValueDTO::getValue, LovValueDTO::getMeaning));
            }

            // 组装数据
            for (PmThickAddvBt line : pmThickAddvBtList) {
                PmThickAddvBtDTO pmThickAddvBtDTO = new PmThickAddvBtDTO();
                BeanUtils.copy(line, pmThickAddvBtDTO);
                pmThickAddvBtDTO.setWholeHeatTreatmentTypeDesc(treatModeMap.getOrDefault(line.getWholeHeatTreatmentType(), line.getWholeHeatTreatmentType()));
                pmThickAddvBtDTO.setMscLineNoDesc(mscLineNoMap.getOrDefault(line.getMscLineNo(), line.getMscLineNo()));
                pmThickAddvBtDTO.setTolTypeCodeDesc(typeCodeMap.getOrDefault(line.getTolTypeCode(), line.getTolTypeCode()));
                resultList.add(pmThickAddvBtDTO);
            }
        }
        return resultList;
    }
}

