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

import com.xisc.pm.app.service.PmIngotThickAddvBtService;
import com.xisc.pm.common.dto.PmIngotThickAddvBtDTO;
import com.xisc.pm.domain.entity.PmIngotThickAddvBt;
import com.xisc.pm.domain.entity.PmIngotThickAddvBtTra;
import com.xisc.pm.domain.repository.PmIngotThickAddvBtRepository;
import com.xisc.pm.domain.repository.PmIngotThickAddvBtTraRepository;
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.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 钢锭厚度余量基准表(PmIngotThickAddvBt)应用服务
 *
 * @author 蒋雨航 yuhang.jiang02@hand-china.com
 * @since 2024-09-05 15:15:06
 */
@Service
public class PmIngotThickAddvBtServiceImpl implements PmIngotThickAddvBtService {

    @Autowired
    private PmIngotThickAddvBtRepository pmIngotThickAddvBtRepository;

    @Autowired
    private PmIngotThickAddvBtTraRepository pmIngotThickAddvBtTraRepository;

    @Autowired
    private LovAdapter lovAdapter;


    @Override
    public Page<PmIngotThickAddvBt> selectList(PageRequest pageRequest, PmIngotThickAddvBt pmIngotThickAddvBt) {
        return PageHelper.doPageAndSort(pageRequest, () -> pmIngotThickAddvBtRepository.selectList(pmIngotThickAddvBt));
    }

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

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

                    // 组合板宽度
                    boolean combinePlateWidthIntervalCheck = Utils.isIntersect(thickAddvBtList.get(i).getCombinePlateWidthFrom(),
                            thickAddvBtList.get(i).getCombinePlateWidthTo(), thickAddvBtList.get(j).getCombinePlateWidthFrom(),
                            thickAddvBtList.get(j).getCombinePlateWidthTo());
                    if (!combinePlateWidthIntervalCheck) {
                        continue;
                    }

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


        // 与数据库记录校验区间是否交叉
        List<String> ingotTypeList = pmIngotThickAddvBtList.stream().map(PmIngotThickAddvBt::getIngotType).distinct()
                .collect(Collectors.toList());
        List<String> heatTreatModeList = pmIngotThickAddvBtList.stream().map(PmIngotThickAddvBt::getHeatTreatMode).distinct()
                .collect(Collectors.toList());
        List<String> rollModeList = pmIngotThickAddvBtList.stream().map(PmIngotThickAddvBt::getRollMode).distinct()
                .collect(Collectors.toList());
        List<String> rollDirectCodeList = pmIngotThickAddvBtList.stream().map(PmIngotThickAddvBt::getRollDirectCode).distinct()
                .collect(Collectors.toList());
        List<Long> idList = pmIngotThickAddvBtList.stream().filter(item -> item.getPitabId() != null).map(PmIngotThickAddvBt::getPitabId).collect(Collectors.toList());
        List<PmIngotThickAddvBt> exisPmIgnotThickAddvBtList = pmIngotThickAddvBtRepository.selectByCondition(Condition.builder(PmIngotThickAddvBt.class)
                .andWhere(Sqls.custom().andEqualTo(PmIngotThickAddvBt.FIELD_TENANT_ID, tenantId))
                        .andWhere(Sqls.custom().andIn(PmIngotThickAddvBt.FIELD_INGOT_TYPE, ingotTypeList))
                        .andWhere(Sqls.custom().andIn(PmIngotThickAddvBt.FIELD_HEAT_TREAT_MODE, heatTreatModeList))
                        .andWhere(Sqls.custom().andIn(PmIngotThickAddvBt.FIELD_ROLL_MODE, rollModeList))
                        .andWhere(Sqls.custom().andIn(PmIngotThickAddvBt.FIELD_ROLL_DIRECT_CODE, rollDirectCodeList))
                        .andWhere(Sqls.custom().andNotIn(PmIngotThickAddvBt.FIELD_PITAB_ID, idList, true))
                .build());
        if (CollectionUtils.isNotEmpty(exisPmIgnotThickAddvBtList)) {
            Map<String, List<PmIngotThickAddvBt>> existAddvMap = exisPmIgnotThickAddvBtList.stream().
                    collect(Collectors.groupingBy(this::getAddvKey));
            for (PmIngotThickAddvBt pmIngotThickAddvBt : pmIngotThickAddvBtList) {
                if (existAddvMap.containsKey(getAddvKey(pmIngotThickAddvBt))) {
                    List<PmIngotThickAddvBt> thickAddvBtList = existAddvMap.get(getAddvKey(pmIngotThickAddvBt));
                    for (PmIngotThickAddvBt ingotThickAddvBt : thickAddvBtList) {
                        // 校验钢板厚度区间是否交叉
                        boolean rollThickIntervalCheck = Utils.isIntersect(pmIngotThickAddvBt.getPlateThickFrom(),
                                pmIngotThickAddvBt.getPlateThickTo(), ingotThickAddvBt.getPlateThickFrom(),
                                ingotThickAddvBt.getPlateThickTo());
                        if (!rollThickIntervalCheck) {
                            continue;
                        }

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

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

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

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

        // 记录历史表
        for (PmIngotThickAddvBt pmIngotThickAddvBt : updateList) {
            PmIngotThickAddvBtTra pmIgnotThickAddvBtTra = new PmIngotThickAddvBtTra();
            BeanUtils.copy(pmIngotThickAddvBt, pmIgnotThickAddvBtTra);

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

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

        for (PmIngotThickAddvBt pmIngotThickAddvBt : insertList) {
            PmIngotThickAddvBtTra pmIngotThickAddvBtTra = new PmIngotThickAddvBtTra();
            BeanUtils.copy(pmIngotThickAddvBt, pmIngotThickAddvBtTra);

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

        }
        // 插入保存或者更新记录到对应履历表
        pmIngotThickAddvBtTraRepository.batchInsertSelective(insertPmMoldSpecBtTraList);
    }
    
    public String getAddvKey(PmIngotThickAddvBt pmIngotThickAddvBt) {
        return pmIngotThickAddvBt.getIngotType() + pmIngotThickAddvBt.getHeatTreatMode() + pmIngotThickAddvBt.getRollMode()
                + pmIngotThickAddvBt.getRollDirectCode();
    }

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

            // 获取时间和当前操作人信息
            Date now = new Date();
            String username = DetailsHelper.getUserDetails().getUsername();
            List<PmIngotThickAddvBtTra> insertPmMoldSpecBtTraList = new ArrayList<>(pmIngotThickAddvBtList.size());
            for (PmIngotThickAddvBt pmIngotThickAddvBt : pmIngotThickAddvBtList) {
                PmIngotThickAddvBtTra pmIngotThickAddvBtTra = new PmIngotThickAddvBtTra();

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

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

    @Override
    public List<PmIngotThickAddvBtDTO> exportList(PmIngotThickAddvBt pmIngotThickAddvBt, Long tenantId) {
        List<PmIngotThickAddvBt> pmIngotThickAddvBtList = pmIngotThickAddvBtRepository.selectList(pmIngotThickAddvBt);
        if (CollectionUtils.isEmpty(pmIngotThickAddvBtList)) {
            return new ArrayList<>();
        }

        // 锭坯型
        List<LovValueDTO> ingotTypeList = lovAdapter.queryLovValue(Constants.LovCode.INGOT_TYPE, tenantId);
        Map<String, String> ingotLovMap = new HashMap<>(ingotTypeList.size());
        if (CollectionUtils.isNotEmpty(ingotTypeList)) {
            ingotLovMap = ingotTypeList.stream().collect(Collectors.toMap(LovValueDTO::getValue, LovValueDTO::getMeaning));
        }
        // 轧制方向
        List<LovValueDTO> rollDirectCodeList = lovAdapter.queryLovValue(Constants.LovCode.BT_ROLL_DIRECT_CODE, tenantId);
        Map<String, String> rollDirectCodeMap = new HashMap<>(rollDirectCodeList.size());
        if (CollectionUtils.isNotEmpty(rollDirectCodeList)) {
            rollDirectCodeMap = rollDirectCodeList.stream().collect(Collectors.toMap(LovValueDTO::getValue, LovValueDTO::getMeaning));
        }

        // 轧制模式
        List<LovValueDTO> rollModeList = lovAdapter.queryLovValue(Constants.LovCode.BT_ROLL_MODE, tenantId);
        Map<String, String> rollModeMap = new HashMap<>(rollDirectCodeList.size());
        if (CollectionUtils.isNotEmpty(rollModeList)) {
            rollModeMap = rollModeList.stream().collect(Collectors.toMap(LovValueDTO::getValue, LovValueDTO::getMeaning));
        }
        List<PmIngotThickAddvBtDTO> resList = new ArrayList<>();
        for (PmIngotThickAddvBt ingotThickAddvBt : pmIngotThickAddvBtList) {
            PmIngotThickAddvBtDTO res = new PmIngotThickAddvBtDTO();
            BeanUtils.copy(ingotThickAddvBt, res);
            res.setIngotTypeDesc(ingotLovMap.getOrDefault(ingotThickAddvBt.getIngotType(), ingotThickAddvBt.getIngotType()));
            res.setRollDirectCodeDesc(rollDirectCodeMap.getOrDefault(ingotThickAddvBt.getRollDirectCode(), ingotThickAddvBt.getRollDirectCode()));
            res.setRollModeDesc(rollModeMap.getOrDefault(ingotThickAddvBt.getRollMode(), ingotThickAddvBt.getRollMode()));
            resList.add(res);
        }
        return resList;
    }
}

