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

import com.xisc.pm.api.dto.export.PmPlateCutLenBtDTO;
import com.xisc.pm.app.service.PmPlateCutLenBtService;
import com.xisc.pm.domain.entity.PmPlateCutLenBt;
import com.xisc.pm.domain.entity.PmPlateCutLenBtTra;
import com.xisc.pm.domain.repository.PmPlateCutLenBtRepository;
import com.xisc.pm.domain.repository.PmPlateCutLenBtTraRepository;
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.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;

/**
 * 钢板切缝切头尾范围基准表(PmPlateCutLenBt)应用服务
 *
 * @author 纪文桃 wentao.ji01@hand-china.com
 * @since 2024-07-24 09:26:44
 */
@Service
public class PmPlateCutLenBtServiceImpl implements PmPlateCutLenBtService {

    private PmPlateCutLenBtRepository pmPlateCutLenBtRepository;

    private PmPlateCutLenBtTraRepository pmPlateCutLenBtTraRepository;

    private LovAdapter lovAdapter;

    public PmPlateCutLenBtServiceImpl(PmPlateCutLenBtRepository pmPlateCutLenBtRepository, PmPlateCutLenBtTraRepository pmPlateCutLenBtTraRepository, LovAdapter lovAdapter) {
        this.pmPlateCutLenBtRepository = pmPlateCutLenBtRepository;
        this.pmPlateCutLenBtTraRepository = pmPlateCutLenBtTraRepository;
        this.lovAdapter = lovAdapter;
    }

    @Override
    public Page<PmPlateCutLenBt> selectList(PageRequest pageRequest, PmPlateCutLenBt pmPlateCutLenBt) {
        return PageHelper.doPageAndSort(pageRequest, () -> pmPlateCutLenBtRepository.selectList(pmPlateCutLenBt));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveData(Long tenantId, List<PmPlateCutLenBt> pmPlateCutLenBtList) {
        // 检查数据列表是否为空，如果为空则直接返回
        if (CollectionUtils.isEmpty(pmPlateCutLenBtList)) {
            return;
        }
        // 新增记录之间校验区间是否交叉
        Map<String, List<PmPlateCutLenBt>> plateThickFromMap = pmPlateCutLenBtList.stream().collect(Collectors.groupingBy(this::getPlateFromKey));
        for (Map.Entry<String, List<PmPlateCutLenBt>> entry : plateThickFromMap.entrySet()) {
            List<PmPlateCutLenBt> plateCutValueList = entry.getValue();
            for (int i = 0; i < plateCutValueList.size() - 1; i++) {
                for (int j = i + 1; j < plateCutValueList.size(); j++) {
                    // 校验钢板厚度区间是否交叉
                    boolean plateThickIntervalCheck = Utils.isIntersect(plateCutValueList.get(i).getPlateThickFrom(), plateCutValueList.get(i).getPlateThickTo(),
                            plateCutValueList.get(j).getPlateThickFrom(), plateCutValueList.get(j).getPlateThickTo());
                    if (!plateThickIntervalCheck) {
                        continue;
                    }

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

                    // 校验板坯厚度起止区间是否交叉
                    boolean slabThickIntervalCheck = Utils.isIntersect(plateCutValueList.get(i).getSlabThickFrom(),
                            plateCutValueList.get(i).getSlabThickTo(), plateCutValueList.get(j).getSlabThickFrom(),
                            plateCutValueList.get(j).getSlabThickTo());
                    if (!slabThickIntervalCheck) {
                        continue;
                    }

                    throw new CommonException("pm.thick_addv_bt_005", plateCutValueList.get(j).getPlateThickFrom(), plateCutValueList.get(j).getPlateThickTo(),
                            plateCutValueList.get(j).getCombinePlateWidthFrom(), plateCutValueList.get(j).getCombinePlateWidthTo(),
                            plateCutValueList.get(j).getSlabThickFrom(),  plateCutValueList.get(j).getSlabThickTo());
                }
            }
        }
        // 获取字段集合，查询数据库该范围内数据
        List<String> brrNeedList = pmPlateCutLenBtList.stream().map(PmPlateCutLenBt::getBrrNeed).distinct().collect(Collectors.toList());
        List<String> rollModeList = pmPlateCutLenBtList.stream().map(PmPlateCutLenBt::getRollMode).distinct().collect(Collectors.toList());
        List<String> rollDirectCodeList = pmPlateCutLenBtList.stream().map(PmPlateCutLenBt::getRollDirectCode).distinct().collect(Collectors.toList());
        List<String> rollLineNoList = pmPlateCutLenBtList.stream().map(PmPlateCutLenBt::getMscLineNo).distinct().collect(Collectors.toList());
        List<Long> idList = pmPlateCutLenBtList.stream().filter(item -> item.getPpclbId() != null).map(PmPlateCutLenBt::getPpclbId).collect(Collectors.toList());
        // 根据提取的条件查询数据库中已存在的PmPlateCutLenBt记录
        List<PmPlateCutLenBt> existPmPlateCutLenBtList = pmPlateCutLenBtRepository.selectByCondition(Condition.builder(PmPlateCutLenBt.class)
                .andWhere(Sqls.custom().andEqualTo(PmPlateCutLenBt.FIELD_TENANT_ID, tenantId))
                .andWhere(Sqls.custom().andIn(PmPlateCutLenBt.FIELD_BRR_NEED, brrNeedList))
                .andWhere(Sqls.custom().andIn(PmPlateCutLenBt.FIELD_ROLL_MODE, rollModeList))
                .andWhere(Sqls.custom().andIn(PmPlateCutLenBt.FIELD_ROLL_DIRECT_CODE, rollDirectCodeList))
                .andWhere(Sqls.custom().andIn(PmPlateCutLenBt.FIELD_MSC_LINE_NO, rollLineNoList))
                .andWhere(Sqls.custom().andNotIn(PmPlateCutLenBt.FIELD_PPCLB_ID, idList, true))
                .build());
        // 与数据库记录校验区间是否交叉
        if (CollectionUtils.isNotEmpty(existPmPlateCutLenBtList)) {
            Map<String, List<PmPlateCutLenBt>> existPlateFromMap = existPmPlateCutLenBtList.stream()
                    .collect(Collectors.groupingBy(this::getPlateFromKey));
            for (PmPlateCutLenBt pmPlateCutLenBt : pmPlateCutLenBtList) {
                if (existPlateFromMap.containsKey(getPlateFromKey(pmPlateCutLenBt))) {
                    List<PmPlateCutLenBt> existCutLenBtList = existPlateFromMap.get(getPlateFromKey(pmPlateCutLenBt));
                    for (PmPlateCutLenBt plateCutLenBt : existCutLenBtList) {
                        // 校验钢板厚度区间是否交叉
                        boolean plateThickIntervalCheck = Utils.isIntersect(pmPlateCutLenBt.getPlateThickFrom(), pmPlateCutLenBt.getPlateThickTo(),
                                plateCutLenBt.getPlateThickFrom(), plateCutLenBt.getPlateThickTo());
                        if (!plateThickIntervalCheck) {
                            continue;
                        }

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

                        // 校验板坯厚度起止区间是否交叉
                        boolean slabThickIntervalCheck = Utils.isIntersect(pmPlateCutLenBt.getSlabThickFrom(),
                                pmPlateCutLenBt.getSlabThickTo(), plateCutLenBt.getSlabThickFrom(),
                                plateCutLenBt.getSlabThickTo());
                        if (!slabThickIntervalCheck) {
                            continue;
                        }

                        throw new CommonException("pm.thick_addv_bt_006", plateCutLenBt.getPlateThickFrom(), plateCutLenBt.getPlateThickTo(),
                                plateCutLenBt.getCombinePlateWidthFrom(), plateCutLenBt.getCombinePlateWidthTo(),
                                plateCutLenBt.getSlabThickFrom(), plateCutLenBt.getSlabThickTo());
                    }
                }
            }
        }

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

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

            // 记录历史表
            for (PmPlateCutLenBt pmPlateCutLenBt : updateList) {
                PmPlateCutLenBtTra pmPlateCutLenBtTra = new PmPlateCutLenBtTra();
                BeanUtils.copy(pmPlateCutLenBt, pmPlateCutLenBtTra);

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

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

            for (PmPlateCutLenBt pmPlateCutLenBt : insertList) {
                PmPlateCutLenBtTra pmPlateCutLenBtTra = new PmPlateCutLenBtTra();
                BeanUtils.copy(pmPlateCutLenBt, pmPlateCutLenBtTra);

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

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

    }

    @Override
    public String getPlateFromKey(PmPlateCutLenBt pmPlateCutLenBt) {
        return pmPlateCutLenBt.getBrrNeed() + "-" + pmPlateCutLenBt.getRollMode() + "-" +
                pmPlateCutLenBt.getRollDirectCode() + "-" + pmPlateCutLenBt.getMscLineNo();
    }

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

            // 获取时间和当前操作人信息
            Date now = new Date();
            String username = DetailsHelper.getUserDetails().getUsername();
            List<PmPlateCutLenBtTra> insertPmMoldSpecBtTraList = new ArrayList<>(pmPlateCutLenBtList.size());
            for (PmPlateCutLenBt pmPlateCutLenBt : pmPlateCutLenBtList) {
                PmPlateCutLenBtTra pmPlateCutLenBtTra = new PmPlateCutLenBtTra();

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

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

    @Override
    public List<PmPlateCutLenBtDTO> exportList(PmPlateCutLenBt pmPlateCutLenBt) {
        List<PmPlateCutLenBt> pmPlateCutLenBtList = pmPlateCutLenBtRepository.selectList(pmPlateCutLenBt);

        // 如果集合为空，则返回
        if (CollectionUtils.isEmpty(pmPlateCutLenBtList)) {
            return Collections.EMPTY_LIST;
        }
        // 获取生效值集含义
        List<LovValueDTO> brrNeedLovList = lovAdapter.queryLovValue(Constants.LovCode.XISC_WHETHER_FLAG_01, pmPlateCutLenBt.getTenantId());
        // 获取切边标记含义
        List<LovValueDTO> withSideFlagList = lovAdapter.queryLovValue(Constants.LovCode.WITH_SIDE_FLAG, pmPlateCutLenBt.getTenantId());
        // 轧制模式含义
        List<LovValueDTO> rollModeList = lovAdapter.queryLovValue(Constants.LovCode.BT_ROLL_MODE, pmPlateCutLenBt.getTenantId());
        // 轧制方向代码含义
        List<LovValueDTO> rollDirectCodeList = lovAdapter.queryLovValue(Constants.LovCode.BT_ROLL_DIRECT_CODE, pmPlateCutLenBt.getTenantId());
        // 设计产线号含义
        List<LovValueDTO> mscLineNoList = lovAdapter.queryLovValue(Constants.LovCode.MSC_LINE_NO, pmPlateCutLenBt.getTenantId());

        Map<String, String> brrNeedLovLovMap = new HashMap<>(brrNeedLovList.size());
        Map<String, String> withSideFlagLovMap = new HashMap<>(withSideFlagList.size());
        Map<String, String> rollModeLovMap = new HashMap<>(rollModeList.size());
        Map<String, String> rollDirectCodeLovMap = new HashMap<>(rollDirectCodeList.size());
        Map<String, String> mscLineNoLovMap = new HashMap<>(mscLineNoList.size());

        // 赋值
        if (CollectionUtils.isNotEmpty(brrNeedLovList)) {
            brrNeedLovLovMap = brrNeedLovList.stream().collect(Collectors.toMap(LovValueDTO::getValue, LovValueDTO::getMeaning));
        }
        if (CollectionUtils.isNotEmpty(withSideFlagList)) {
            withSideFlagLovMap = withSideFlagList.stream().collect(Collectors.toMap(LovValueDTO::getValue, LovValueDTO::getMeaning));
        }
        if (CollectionUtils.isNotEmpty(rollModeList)) {
            rollModeLovMap = rollModeList.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(mscLineNoList)) {
            mscLineNoLovMap = mscLineNoList.stream().collect(Collectors.toMap(LovValueDTO::getValue, LovValueDTO::getMeaning));
        }

        List<PmPlateCutLenBtDTO> resultList = new ArrayList<>(pmPlateCutLenBtList.size());
        for (PmPlateCutLenBt line : pmPlateCutLenBtList) {
            PmPlateCutLenBtDTO pmPlateCutLenBtDTO = new PmPlateCutLenBtDTO();
            if (!brrNeedLovLovMap.isEmpty()) {
                line.setBrrNeedDesc(brrNeedLovLovMap.getOrDefault(line.getBrrNeed(), ""));
            }
            if (!rollModeLovMap.isEmpty()) {
                line.setRollModeDesc(rollModeLovMap.getOrDefault(line.getRollMode(), ""));
            }
            if (!rollDirectCodeLovMap.isEmpty()) {
                line.setRollDirectCodeDesc(rollDirectCodeLovMap.getOrDefault(line.getRollDirectCode(), ""));
            }
            if (!mscLineNoLovMap.isEmpty()) {
                line.setMscLineNoDesc(mscLineNoLovMap.getOrDefault(line.getMscLineNo(), ""));
            }
            BeanUtils.copy(line, pmPlateCutLenBtDTO);
            resultList.add(pmPlateCutLenBtDTO);
        }
        return resultList;
    }
}

