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

import com.xisc.pm.api.dto.export.PmPdTmpYieldBtDTO;
import com.xisc.pm.app.service.PmPdTmpYieldBtService;
import com.xisc.pm.domain.entity.PmPdTmpYieldBt;
import com.xisc.pm.domain.entity.PmPdTmpYieldBtTra;
import com.xisc.pm.domain.repository.PmPdTmpYieldBtRepository;
import com.xisc.pm.domain.repository.PmPdTmpYieldBtTraRepository;
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;

/**
 * 组板临时收得率基准表(PmPdTmpYieldBt)应用服务
 *
 * @author 纪文桃 wentao.ji01@hand-china.com
 * @since 2024-07-24 11:02:23
 */
@Service
public class PmPdTmpYieldBtServiceImpl implements PmPdTmpYieldBtService {

    private PmPdTmpYieldBtRepository pmPdTmpYieldBtRepository;

    private PmPdTmpYieldBtTraRepository pmPdTmpYieldBtTraRepository;

    private LovAdapter lovAdapter;

    public PmPdTmpYieldBtServiceImpl(PmPdTmpYieldBtRepository pmPdTmpYieldBtRepository, PmPdTmpYieldBtTraRepository pmPdTmpYieldBtTraRepository, LovAdapter lovAdapter) {
        this.pmPdTmpYieldBtRepository = pmPdTmpYieldBtRepository;
        this.pmPdTmpYieldBtTraRepository = pmPdTmpYieldBtTraRepository;
        this.lovAdapter = lovAdapter;
    }


    @Override
    public Page<PmPdTmpYieldBt> selectList(PageRequest pageRequest, PmPdTmpYieldBt pmPdTmpYieldBt) {
        return PageHelper.doPageAndSort(pageRequest, () -> pmPdTmpYieldBtRepository.selectList(pmPdTmpYieldBt));
    }

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

        // 新增记录之间校验区间是否交叉
        Map<String, List<PmPdTmpYieldBt>> plateFromMap = pmPdTmpYieldBtList.stream().collect(Collectors.groupingBy(this::getTmpKey));
        for (Map.Entry<String, List<PmPdTmpYieldBt>> entry : plateFromMap.entrySet()) {
            List<PmPdTmpYieldBt> pdTmpYieldBtList = entry.getValue();
            for (int i = 0; i < pdTmpYieldBtList.size() - 1; i++) {
                for (int j = i + 1; j < pdTmpYieldBtList.size(); j++) {
                    // 校验钢板厚度区间是否交叉
                    boolean plateThickIntervalCheck = Utils.isIntersect(pdTmpYieldBtList.get(i).getPlateThickFrom(), pdTmpYieldBtList.get(i).getPlateThickTo(),
                            pdTmpYieldBtList.get(j).getPlateThickFrom(), pdTmpYieldBtList.get(j).getPlateThickTo());
                    if (!plateThickIntervalCheck) {
                        continue;
                    }
                    // 校验板坯厚度区间是否交叉
                    boolean normalCutLenIntervalCheck = Utils.isIntersect(pdTmpYieldBtList.get(i).getSlabThickFrom(), pdTmpYieldBtList.get(i).getSlabThickTo(),
                            pdTmpYieldBtList.get(j).getSlabThickFrom(), pdTmpYieldBtList.get(j).getSlabThickTo());
                    if (!normalCutLenIntervalCheck) {
                        continue;
                    }

                    // 校验板坯宽度区间是否交叉
                    boolean qtCutLenIntervalCheck = Utils.isIntersect(pdTmpYieldBtList.get(i).getSlabWidthFrom(), pdTmpYieldBtList.get(i).getSlabWidthTo(),
                            pdTmpYieldBtList.get(j).getSlabWidthFrom(), pdTmpYieldBtList.get(j).getSlabWidthTo());
                    if (!qtCutLenIntervalCheck) {
                        continue;
                    }

                    throw new CommonException("pm.cut_place_bt_005",
                            pdTmpYieldBtList.get(j).getSlabThickFrom(), pdTmpYieldBtList.get(j).getSlabThickTo(),
                            pdTmpYieldBtList.get(j).getSlabWidthFrom(), pdTmpYieldBtList.get(j).getSlabWidthTo(),
                            pdTmpYieldBtList.get(j).getPlateThickFrom(), pdTmpYieldBtList.get(j).getPlateThickTo());
                }
            }
        }

        // 与数据库记录校验区间是否交叉
        List<String> ccTypeList = pmPdTmpYieldBtList.stream().map(PmPdTmpYieldBt::getCcType).distinct().collect(Collectors.toList());
        List<String> pdProdCodeHpList = pmPdTmpYieldBtList.stream().map(PmPdTmpYieldBt::getProdCodeHp).distinct().collect(Collectors.toList());
        List<String> withSideFlagList = pmPdTmpYieldBtList.stream().map(PmPdTmpYieldBt::getWithSideFlag).distinct().collect(Collectors.toList());
        List<String> rollineNoList = pmPdTmpYieldBtList.stream().map(PmPdTmpYieldBt::getRollLineNo).distinct().collect(Collectors.toList());
        List<Long> idList = pmPdTmpYieldBtList.stream().filter(item -> item.getPptybId() != null).map(PmPdTmpYieldBt::getPptybId).collect(Collectors.toList());
        List<PmPdTmpYieldBt> existPmPdTmpYieldBtList = pmPdTmpYieldBtRepository.selectByCondition(Condition.builder(PmPdTmpYieldBt.class)
                        .andWhere(Sqls.custom().andIn(PmPdTmpYieldBt.FIELD_CC_TYPE, ccTypeList))
                        .andWhere(Sqls.custom().andIn(PmPdTmpYieldBt.FIELD_PROD_CODE_HP, pdProdCodeHpList))
                        .andWhere(Sqls.custom().andIn(PmPdTmpYieldBt.FIELD_WITH_SIDE_FLAG, withSideFlagList))
                        .andWhere(Sqls.custom().andIn(PmPdTmpYieldBt.FIELD_ROLL_LINE_NO, rollineNoList))
                        .andWhere(Sqls.custom().andNotIn(PmPdTmpYieldBt.FIELD_PPTYB_ID, idList, true))
                .andWhere(Sqls.custom().andEqualTo(PmPdTmpYieldBt.FIELD_TENANT_ID, tenantId))
                .build());
        if (CollectionUtils.isNotEmpty(existPmPdTmpYieldBtList)) {
            Map<String, List<PmPdTmpYieldBt>> existMap = existPmPdTmpYieldBtList.stream().collect(Collectors.groupingBy(this::getTmpKey));
            for (PmPdTmpYieldBt pmPdTmpYieldBt : pmPdTmpYieldBtList) {
                if (existMap.containsKey(getTmpKey(pmPdTmpYieldBt))) {
                    List<PmPdTmpYieldBt> existYieldBtList = existMap.get(getTmpKey(pmPdTmpYieldBt));
                    for (PmPdTmpYieldBt pdTmpYieldBt : existYieldBtList) {
                        // 校验钢板厚度区间是否交叉
                        boolean plateThickIntervalCheck = Utils.isIntersect(pmPdTmpYieldBt.getPlateThickFrom(), pmPdTmpYieldBt.getPlateThickTo(),
                                pdTmpYieldBt.getPlateThickFrom(), pdTmpYieldBt.getPlateThickTo());
                        if (!plateThickIntervalCheck) {
                            continue;
                        }
                        // 校验板坯厚度区间是否交叉
                        boolean normalCutLenIntervalCheck = Utils.isIntersect(pmPdTmpYieldBt.getSlabThickFrom(), pmPdTmpYieldBt.getSlabThickTo(),
                                pdTmpYieldBt.getSlabThickFrom(), pdTmpYieldBt.getSlabThickTo());
                        if (!normalCutLenIntervalCheck) {
                            continue;
                        }

                        // 校验板坯宽度区间是否交叉
                        boolean qtCutLenIntervalCheck = Utils.isIntersect(pmPdTmpYieldBt.getSlabWidthFrom(), pmPdTmpYieldBt.getSlabWidthTo(),
                                pdTmpYieldBt.getSlabWidthFrom(), pdTmpYieldBt.getSlabWidthTo());
                        if (!qtCutLenIntervalCheck) {
                            continue;
                        }

                        throw new CommonException("pm.cut_place_bt_002",
                                pdTmpYieldBt.getSlabThickFrom(), pdTmpYieldBt.getSlabThickTo(),
                                pdTmpYieldBt.getSlabWidthFrom(), pdTmpYieldBt.getSlabWidthTo(),
                                pdTmpYieldBt.getPlateThickFrom(), pdTmpYieldBt.getPlateThickTo());
                    }
                }
            }
        }

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

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

        // 记录历史表
        for (PmPdTmpYieldBt pmPdTmpYieldBt : updateList) {
            PmPdTmpYieldBtTra pmPdTmpYieldBtTra = new PmPdTmpYieldBtTra();
            BeanUtils.copy(pmPdTmpYieldBt, pmPdTmpYieldBtTra);

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

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

        for (PmPdTmpYieldBt pmPdTmpYieldBt : insertList) {
            PmPdTmpYieldBtTra pmPdTmpYieldBtTra = new PmPdTmpYieldBtTra();
            BeanUtils.copy(pmPdTmpYieldBt, pmPdTmpYieldBtTra);

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

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

    @Override
    public String getTmpKey(PmPdTmpYieldBt pmPdTmpYieldBt) {
        return pmPdTmpYieldBt.getCcType() + pmPdTmpYieldBt.getProdCodeHp() + pmPdTmpYieldBt.getWithSideFlag() + pmPdTmpYieldBt.getRollLineNo();
    }

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

            // 获取时间和当前操作人信息
            Date now = new Date();
            String username = DetailsHelper.getUserDetails().getUsername();
            List<PmPdTmpYieldBtTra> insertPmMoldSpecBtTraList = new ArrayList<>(pmPdTmpYieldBtList.size());
            for (PmPdTmpYieldBt pmPdTmpYieldBt : pmPdTmpYieldBtList) {
                PmPdTmpYieldBtTra pmPdTmpYieldBtTra = new PmPdTmpYieldBtTra();

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

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

    @Override
    public List<PmPdTmpYieldBtDTO> exportList(PmPdTmpYieldBt pmPdTmpYieldBt) {
        List<PmPdTmpYieldBt> pmPdTmpYieldBtList = pmPdTmpYieldBtRepository.selectList(pmPdTmpYieldBt);

        // 如果集合为空，则返回
        if (CollectionUtils.isEmpty(pmPdTmpYieldBtList)) {
            return Collections.emptyList();
        }
        // 获取连铸机类型含义
        List<LovValueDTO> cgTypeLovList = lovAdapter.queryLovValue(Constants.LovCode.BT_CC_TYPE, pmPdTmpYieldBt.getTenantId());
        // 获取厚板品种代码含义
        List<LovValueDTO> prodCodeHpLovList = lovAdapter.queryLovValue(Constants.LovCode.TM_PROD_CODE_HP, pmPdTmpYieldBt.getTenantId());
        // 获取切边标记含义
        List<LovValueDTO> withSideFlagList = lovAdapter.queryLovValue(Constants.LovCode.WITH_SIDE_FLAG, pmPdTmpYieldBt.getTenantId());
        // 轧制产线号含义
        List<LovValueDTO> rollLineNoList = lovAdapter.queryLovValue(Constants.LovCode.ROLL_LINE_NO, pmPdTmpYieldBt.getTenantId());
        Map<String, String> cgTypeLovMap = new HashMap<>(cgTypeLovList.size());
        Map<String, String> prodCodeHpLovMap = new HashMap<>(prodCodeHpLovList.size());
        Map<String, String> withSideFlagLovMap = new HashMap<>(withSideFlagList.size());
        Map<String, String> rollLineNoLovMap = new HashMap<>(rollLineNoList.size());

        // 赋值
        if (CollectionUtils.isNotEmpty(cgTypeLovList)) {
            cgTypeLovMap = cgTypeLovList.stream().collect(Collectors.toMap(LovValueDTO::getValue, LovValueDTO::getMeaning));
        }
        if (CollectionUtils.isNotEmpty(prodCodeHpLovList)) {
            prodCodeHpLovMap = prodCodeHpLovList.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(rollLineNoList)) {
            rollLineNoLovMap = rollLineNoList.stream().collect(Collectors.toMap(LovValueDTO::getValue, LovValueDTO::getMeaning));
        }

        List<PmPdTmpYieldBtDTO> resultList = new ArrayList<>(pmPdTmpYieldBtList.size());
        for (PmPdTmpYieldBt line : pmPdTmpYieldBtList) {
            if (!cgTypeLovMap.isEmpty()) {
                line.setCcTypeDesc(cgTypeLovMap.getOrDefault(line.getCcType(), ""));
            }
            if (!prodCodeHpLovMap.isEmpty()) {
                line.setProdCodeHpDesc(prodCodeHpLovMap.getOrDefault(line.getProdCodeHp(), ""));
            }
            if (!withSideFlagLovMap.isEmpty()) {
                line.setWithSideFlagDesc(withSideFlagLovMap.getOrDefault(line.getWithSideFlag(), ""));
            }
            if (!rollLineNoLovMap.isEmpty()) {
                line.setRollLineNoDesc(rollLineNoLovMap.getOrDefault(line.getRollLineNo(), ""));
            }
            PmPdTmpYieldBtDTO pmPdTmpYieldBtDTO = new PmPdTmpYieldBtDTO();
            BeanUtils.copy(line, pmPdTmpYieldBtDTO);
            resultList.add(pmPdTmpYieldBtDTO);
        }

        return resultList;
    }
}

