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

import com.xisc.pm.api.dto.PmIngotSpecTrimBtDTO;
import com.xisc.pm.app.service.PmIngotSpecTrimBtService;
import com.xisc.pm.domain.entity.PmIngotSpecTrimBt;
import com.xisc.pm.domain.entity.PmIngotSpecTrimBtTra;
import com.xisc.pm.domain.repository.PmIngotSpecTrimBtRepository;
import com.xisc.pm.domain.repository.PmIngotSpecTrimBtTraRepository;
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.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 钢锭轧制规格及切边量基准表(PmIgnotSpecTrimBt)应用服务
 *
 * @author 纪文桃 wentao.ji01@hand-china.com
 * @since 2024-07-24 15:01:55
 */
@Service
public class PmIngotSpecTrimBtServiceImpl implements PmIngotSpecTrimBtService {

    @Autowired
    private PmIngotSpecTrimBtRepository pmIngotSpecTrimBtRepository;

    @Autowired
    private PmIngotSpecTrimBtTraRepository pmIngotSpecTrimBtTraRepository;

    @Autowired
    private LovAdapter lovAdapter;


    @Override
    public Page<PmIngotSpecTrimBt> selectList(PageRequest pageRequest, PmIngotSpecTrimBt pmIngotSpecTrimBt) {
        return PageHelper.doPageAndSort(pageRequest, () -> pmIngotSpecTrimBtRepository.selectList(pmIngotSpecTrimBt));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveData(Long tenantId, List<PmIngotSpecTrimBt> pmIngotSpecTrimBtList) {
        // 检查数据列表是否为空，如果为空则直接返回
        if (CollectionUtils.isEmpty(pmIngotSpecTrimBtList)) {
            return ;
        }

        // 新增记录之间校验区间是否交叉
        Map<String, List<PmIngotSpecTrimBt>> pmIngotSpecTrimBtMap = pmIngotSpecTrimBtList.stream()
                .collect(Collectors.groupingBy(this::getTrimKey));
        for (Map.Entry<String, List<PmIngotSpecTrimBt>> entry : pmIngotSpecTrimBtMap.entrySet()) {
            List<PmIngotSpecTrimBt> ingotSpecTrimBtList = entry.getValue();
            for (int i = 0; i < ingotSpecTrimBtList.size() - 1; i++) {
                for (int j = i + 1; j < ingotSpecTrimBtList.size(); j++) {
                    // 校验轧制厚度区间是否交叉
                    boolean slabThickIntervalCheck = Utils.isIntersect(ingotSpecTrimBtList.get(i).getMinRollThick(), 
                            ingotSpecTrimBtList.get(i).getMaxRollThick(), ingotSpecTrimBtList.get(j).getMinRollThick(),
                            ingotSpecTrimBtList.get(j).getMaxRollThick());
                    if (!slabThickIntervalCheck) {
                        continue;
                    }

                    // 校验轧制宽度区间是否交叉。
                    boolean rollWidthIntervalCheck = Utils.isIntersect(ingotSpecTrimBtList.get(i).getMinRollWidth(),
                            ingotSpecTrimBtList.get(i).getMaxRollWidth(), ingotSpecTrimBtList.get(j).getMinRollWidth(), 
                            ingotSpecTrimBtList.get(j).getMaxRollWidth());
                    if (!rollWidthIntervalCheck) {
                        continue;
                    }

                    // 校验轧制长度区间是否交叉。
                    boolean rollLenIntervalCheck = Utils.isIntersect(ingotSpecTrimBtList.get(i).getRollLenFrom(), 
                            ingotSpecTrimBtList.get(i).getRollLenTo(), ingotSpecTrimBtList.get(j).getRollLenFrom(), 
                            ingotSpecTrimBtList.get(j).getRollLenTo());
                    if (!rollLenIntervalCheck) {
                        continue;
                    }

                    throw new CommonException("pm.ignot_spec_trim_bt_001",
                            ingotSpecTrimBtList.get(j).getMinRollThick(), ingotSpecTrimBtList.get(j).getMaxRollThick(),
                            ingotSpecTrimBtList.get(j).getMinRollWidth(), ingotSpecTrimBtList.get(j).getMaxRollWidth(),
                            ingotSpecTrimBtList.get(j).getRollLenFrom(), ingotSpecTrimBtList.get(j).getRollLenTo());

                }
            }
        }
        // 与数据库记录校验区间是否交叉
        List<String> ingotTypeList = pmIngotSpecTrimBtList.stream().map(PmIngotSpecTrimBt::getIngotType).distinct().collect(Collectors.toList());
        List<String> guaranteeQualityList = pmIngotSpecTrimBtList.stream().map(PmIngotSpecTrimBt::getGuaranteeQuality).distinct().collect(Collectors.toList());
        List<String> rollLineNoList = pmIngotSpecTrimBtList.stream().map(PmIngotSpecTrimBt::getRollLineNo).distinct().collect(Collectors.toList());
        List<String> withSideFlagList = pmIngotSpecTrimBtList.stream().map(PmIngotSpecTrimBt::getWithSideFlag).distinct().collect(Collectors.toList());
        List<String> rollDirectCodeList = pmIngotSpecTrimBtList.stream().map(PmIngotSpecTrimBt::getRollDirectCode).distinct().collect(Collectors.toList());
        List<Long> idList = pmIngotSpecTrimBtList.stream().filter(item -> item.getPistbId() != null).map(PmIngotSpecTrimBt::getPistbId).collect(Collectors.toList());
        List<PmIngotSpecTrimBt> exisPmIngotSpecTrimBtList = pmIngotSpecTrimBtRepository.selectByCondition(Condition.builder(PmIngotSpecTrimBt.class)
                        .andWhere(Sqls.custom().andIn(PmIngotSpecTrimBt.FIELD_INGOT_TYPE, ingotTypeList))
                        .andWhere(Sqls.custom().andIn(PmIngotSpecTrimBt.FIELD_GUARANTEE_QUALITY, guaranteeQualityList))
                        .andWhere(Sqls.custom().andIn(PmIngotSpecTrimBt.FIELD_ROLL_LINE_NO, rollLineNoList))
                        .andWhere(Sqls.custom().andIn(PmIngotSpecTrimBt.FIELD_WITH_SIDE_FLAG, withSideFlagList))
                        .andWhere(Sqls.custom().andIn(PmIngotSpecTrimBt.FIELD_ROLL_DIRECT_CODE, rollDirectCodeList))
                        .andWhere(Sqls.custom().andNotIn(PmIngotSpecTrimBt.FIELD_PISTB_ID, idList, true))
                .andWhere(Sqls.custom().andEqualTo(PmIngotSpecTrimBt.FIELD_TENANT_ID, tenantId))
                .build());
        if (CollectionUtils.isNotEmpty(exisPmIngotSpecTrimBtList)) {
            Map<String, List<PmIngotSpecTrimBt>> existMap = exisPmIngotSpecTrimBtList.stream().collect(Collectors.groupingBy(this::getTrimKey));
            for (PmIngotSpecTrimBt pmIngotSpecTrimBt : pmIngotSpecTrimBtList) {
                if (existMap.containsKey(getTrimKey(pmIngotSpecTrimBt))) {
                    List<PmIngotSpecTrimBt> existSpecTrimBtList = existMap.get(getTrimKey(pmIngotSpecTrimBt));
                    for (PmIngotSpecTrimBt ingotSpecTrimBt : existSpecTrimBtList) {
                        // 校验轧制厚度区间是否交叉
                        boolean rollThickIntervalCheck = Utils.isIntersect(pmIngotSpecTrimBt.getMinRollThick(),
                                pmIngotSpecTrimBt.getMaxRollThick(), ingotSpecTrimBt.getMinRollThick(),
                                ingotSpecTrimBt.getMaxRollThick());
                        if (!rollThickIntervalCheck) {
                            continue;
                        }

                        // 校验轧制宽度区间是否交叉
                        boolean rollWidthIntervalCheck = Utils.isIntersect(pmIngotSpecTrimBt.getMinRollWidth(),
                                pmIngotSpecTrimBt.getMaxRollWidth(), ingotSpecTrimBt.getMinRollWidth(),
                                ingotSpecTrimBt.getMaxRollWidth());
                        if (!rollWidthIntervalCheck) {
                            continue;
                        }

                        // 校验轧制长度区间是否交叉
                        boolean rollLenIntervalCheck = Utils.isIntersect(pmIngotSpecTrimBt.getRollLenFrom(),
                                pmIngotSpecTrimBt.getRollLenTo(), ingotSpecTrimBt.getRollLenFrom(),
                                ingotSpecTrimBt.getRollLenTo());
                        if (!rollLenIntervalCheck) {
                            continue;
                        }

                        throw new CommonException("pm.ignot_spec_trim_bt_002",
                                ingotSpecTrimBt.getMinRollThick(), ingotSpecTrimBt.getMaxRollThick(),
                                ingotSpecTrimBt.getMinRollWidth(), ingotSpecTrimBt.getMaxRollWidth(),
                                ingotSpecTrimBt.getRollLenFrom(), ingotSpecTrimBt.getRollLenTo());
                    }
                }
            }
        }

        // 获取当前时间及操作人信息
        Date now = new Date();
        String username = DetailsHelper.getUserDetails().getUsername();
        List<PmIngotSpecTrimBtTra> insertPmMoldSpecBtTraList = new ArrayList<>(pmIngotSpecTrimBtList.size());

        // 分离需要插入和更新的列表
        List<PmIngotSpecTrimBt> insertList = pmIngotSpecTrimBtList.stream().filter(line -> line.getPistbId() == null).collect(Collectors.toList());
        List<PmIngotSpecTrimBt> updateList = pmIngotSpecTrimBtList.stream().filter(line -> line.getPistbId() != null).collect(Collectors.toList());

        // 记录历史表
        for (PmIngotSpecTrimBt pmIngotSpecTrimBt : updateList) {
            PmIngotSpecTrimBtTra pmIngotSpecTrimBtTra = new PmIngotSpecTrimBtTra();
            BeanUtils.copy(pmIngotSpecTrimBt, pmIngotSpecTrimBtTra);

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

        }
        // 更新或者新增
        pmIngotSpecTrimBtRepository.batchUpdateByPrimaryKey(updateList);
        pmIngotSpecTrimBtRepository.batchInsertSelective(insertList);

        for (PmIngotSpecTrimBt pmIngotSpecTrimBt : insertList) {
            PmIngotSpecTrimBtTra pmIngotSpecTrimBtTra = new PmIngotSpecTrimBtTra();
            BeanUtils.copy(pmIngotSpecTrimBt, pmIngotSpecTrimBtTra);

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

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

    }

    @Override
    public String getTrimKey(PmIngotSpecTrimBt pmIngotSpecTrimBt) {
        return pmIngotSpecTrimBt.getIngotType() + pmIngotSpecTrimBt.getGuaranteeQuality() + pmIngotSpecTrimBt.getRollLineNo()
                + pmIngotSpecTrimBt.getWithSideFlag() + pmIngotSpecTrimBt.getRollDirectCode();
    }

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

            // 获取当前时间和用户账号
            Date now = new Date();
            String username = DetailsHelper.getUserDetails().getUsername();
            List<PmIngotSpecTrimBtTra> insertPmMoldSpecBtTraList = new ArrayList<>(pmIngotSpecTrimBtList.size());
            for (PmIngotSpecTrimBt pmIngotSpecTrimBt : pmIngotSpecTrimBtList) {
                PmIngotSpecTrimBtTra pmIngotSpecTrimBtTra = new PmIngotSpecTrimBtTra();

                // 设置操作类型为删除（D），并记录操作时间和服务用户
                BeanUtils.copy(pmIngotSpecTrimBt, pmIngotSpecTrimBtTra);
                pmIngotSpecTrimBtTra.setOperationType("D");
                pmIngotSpecTrimBtTra.setOperationTime(now);
                pmIngotSpecTrimBtTra.setOperationUser(username);
                insertPmMoldSpecBtTraList.add(pmIngotSpecTrimBtTra);

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

    @Override
    public List<PmIngotSpecTrimBtDTO> exportList(Long tenantId, PmIngotSpecTrimBt pmIngotSpecTrimBt) {
        List<PmIngotSpecTrimBt> pmIngotSpecTrimBtList = pmIngotSpecTrimBtRepository.selectList(pmIngotSpecTrimBt);
        // 如果集合为空，则返回
        if (CollectionUtils.isEmpty(pmIngotSpecTrimBtList)) {
            return Collections.EMPTY_LIST;
        }
        List<PmIngotSpecTrimBtDTO> resultList = new ArrayList<>();
        // 是否保性能
        List<LovValueDTO> flagList = lovAdapter.queryLovValue(Constants.LovCode.XISC_WHETHER_FLAG_01, tenantId);
        Map<String, String> flagLovMap = new HashMap<>(flagList.size());
        // 锭坯型
        List<LovValueDTO> ingotTypeList = lovAdapter.queryLovValue(Constants.LovCode.INGOT_TYPE, tenantId);
        Map<String, String> ingotLovMap = new HashMap<>(ingotTypeList.size());
        // 切边标记
        List<LovValueDTO> withSideList = lovAdapter.queryLovValue(Constants.LovCode.WITH_SIDE_FLAG, tenantId);
        Map<String, String> withSideLovMap = new HashMap<>(ingotTypeList.size());
        // 轧制方向代码
        List<LovValueDTO> rollDirectCodeList = lovAdapter.queryLovValue(Constants.LovCode.BT_ROLL_DIRECT_CODE, tenantId);
        Map<String, String> rollDirectCodeLovMap = new HashMap<>(ingotTypeList.size());
        // 轧制产线号
        List<LovValueDTO> rollLineNoList = lovAdapter.queryLovValue(Constants.LovCode.ROLL_LINE_NO, tenantId);
        Map<String, String> rollLineNoLovMap = new HashMap<>(ingotTypeList.size());
        // 赋值
        if (CollectionUtils.isNotEmpty(flagList)) {
            flagLovMap = flagList.stream().collect(Collectors.toMap(LovValueDTO::getValue, LovValueDTO::getMeaning));
        }
        if (CollectionUtils.isNotEmpty(ingotTypeList)) {
            ingotLovMap = ingotTypeList.stream().collect(Collectors.toMap(LovValueDTO::getValue, LovValueDTO::getMeaning));
        }
        if (CollectionUtils.isNotEmpty(withSideList)) {
            withSideLovMap = withSideList.stream().collect(Collectors.toMap(LovValueDTO::getValue, LovValueDTO::getMeaning));
        }
        if (CollectionUtils.isNotEmpty(rollDirectCodeList)) {
            rollDirectCodeLovMap = rollDirectCodeList.stream().collect(Collectors.toMap(LovValueDTO::getValue, LovValueDTO::getMeaning));
        }
        if (CollectionUtils.isNotEmpty(rollLineNoList)) {
            rollLineNoLovMap = rollLineNoList.stream().collect(Collectors.toMap(LovValueDTO::getValue, LovValueDTO::getMeaning));
        }
        for (PmIngotSpecTrimBt line : pmIngotSpecTrimBtList) {
            PmIngotSpecTrimBtDTO dto = new PmIngotSpecTrimBtDTO();
            BeanUtils.copy(line, dto);
            dto.setIngotTypeDesc(ingotLovMap.getOrDefault(line.getIngotType(), line.getIngotType()));
            dto.setGuaranteeQualityDesc(flagLovMap.getOrDefault(line.getGuaranteeQuality(), line.getGuaranteeQuality()));
            dto.setWithSideFlagDesc(withSideLovMap.getOrDefault(line.getWithSideFlag(), line.getWithSideFlag()));
            dto.setRollDirectCodeDesc(rollDirectCodeLovMap.getOrDefault(line.getRollDirectCode(), line.getRollDirectCode()));
            dto.setRollLineNoDesc(rollLineNoLovMap.getOrDefault(line.getRollLineNo(), line.getRollLineNo()));
            resultList.add(dto);
        }
        return resultList;
    }
}

