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

import com.xisc.pm.app.service.PmCutPlaceBtService;
import com.xisc.pm.domain.entity.PmCutPlaceBt;
import com.xisc.pm.domain.entity.PmCutPlaceBtTra;
import com.xisc.pm.domain.repository.PmCutPlaceBtRepository;
import com.xisc.pm.domain.repository.PmCutPlaceBtTraRepository;
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.mybatis.domian.Condition;
import org.hzero.mybatis.util.Sqls;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 粗切位置决定基准表(PmCutPlaceBt)应用服务
 *
 * @author 纪文桃 wentao.ji01@hand-china.com
 * @since 2024-07-24 08:40:39
 */
@Service
public class PmCutPlaceBtServiceImpl implements PmCutPlaceBtService {

    private PmCutPlaceBtRepository pmCutPlaceBtRepository;

    private PmCutPlaceBtTraRepository pmCutPlaceBtTraRepository;

    public PmCutPlaceBtServiceImpl(PmCutPlaceBtRepository pmCutPlaceBtRepository, PmCutPlaceBtTraRepository pmCutPlaceBtTraRepository) {
        this.pmCutPlaceBtRepository = pmCutPlaceBtRepository;
        this.pmCutPlaceBtTraRepository = pmCutPlaceBtTraRepository;
    }

    @Override
    public Page<PmCutPlaceBt> selectList(PageRequest pageRequest, PmCutPlaceBt pmCutPlaceBt) {
        return PageHelper.doPageAndSort(pageRequest, () -> pmCutPlaceBtRepository.selectList(pmCutPlaceBt));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveData(Long tenantId, List<PmCutPlaceBt> pmCutPlaceBtList) {
        // 如果列表为空，则直接返回，不做任何操作
        if (CollectionUtils.isEmpty(pmCutPlaceBtList)) {
            return;
        }

        // 新增记录之间校验区间是否交叉-其他条件相同时，判断钢板厚度
        Map<String, List<PmCutPlaceBt>> plateThickKeyMap = pmCutPlaceBtList.stream().collect(Collectors.groupingBy(this::getPlateFromKey));
        for (Map.Entry<String, List<PmCutPlaceBt>> entry : plateThickKeyMap.entrySet()) {
            List<PmCutPlaceBt> placeBtList = entry.getValue();
            // 新增记录之间校验区间是否交叉
            for (int i = 0; i < placeBtList.size() - 1; i++) {
                for (int j = i + 1; j < placeBtList.size(); j++) {
                    // 检查钢板厚度区间是否交叉
                    boolean slabThickIntervalCheck = Utils.isIntersect(placeBtList.get(i).getPlateThickFrom(),
                            placeBtList.get(i).getPlateThickTo(), placeBtList.get(j).getPlateThickFrom(),
                            placeBtList.get(j).getPlateThickTo());
                    if (slabThickIntervalCheck) {
                        throw new CommonException("pm.cut_place_bt_004", placeBtList.get(j).getPlateThickFrom(),
                                placeBtList.get(j).getPlateThickTo());
                    }
                }
            }
        }

        // 与数据库记录校验区间是否交叉
        List<String> formPlateModeFirstList = pmCutPlaceBtList.stream().map(PmCutPlaceBt::getFormPlateModeFirst).distinct().collect(Collectors.toList());
        List<String> rollLineNoList = pmCutPlaceBtList.stream().map(PmCutPlaceBt::getRollLineNo).distinct().collect(Collectors.toList());
        List<Long> idList = pmCutPlaceBtList.stream().filter(pmCutPlaceBt -> pmCutPlaceBt.getPcpbId() != null).map(PmCutPlaceBt::getPcpbId).collect(Collectors.toList());
        List<PmCutPlaceBt> existPmCutPlaceBtList = pmCutPlaceBtRepository.selectByCondition(Condition.builder(PmCutPlaceBt.class)
                .andWhere(Sqls.custom().andEqualTo(PmCutPlaceBt.FIELD_TENANT_ID, tenantId))
                .andWhere(Sqls.custom().andIn(PmCutPlaceBt.FIELD_FORM_PLATE_MODE_FIRST, formPlateModeFirstList))
                .andWhere(Sqls.custom().andIn(PmCutPlaceBt.FIELD_ROLL_LINE_NO, rollLineNoList))
                .andWhere(Sqls.custom().andNotIn(PmCutPlaceBt.FIELD_PCPB_ID, idList, true))
                .build());
        if (CollectionUtils.isNotEmpty(existPmCutPlaceBtList)) {
            Map<String, List<PmCutPlaceBt>> existPlateThickKeyMap = existPmCutPlaceBtList.stream().collect(Collectors.groupingBy(this::getPlateFromKey));
            for (PmCutPlaceBt pmCutPlaceBt : pmCutPlaceBtList) {
                // 如果数据库数据存在该条记录，则判断区间是否交叉
                if (existPlateThickKeyMap.containsKey(getPlateFromKey(pmCutPlaceBt))) {
                    List<PmCutPlaceBt> cutPlaceBtList = existPlateThickKeyMap.get(getPlateFromKey(pmCutPlaceBt));
                    for (PmCutPlaceBt cutPlaceBt : cutPlaceBtList) {
                        // 检查钢板厚度区间是否交叉
                        boolean slabThickIntervalCheck = Utils.isIntersect(pmCutPlaceBt.getPlateThickFrom(),
                                pmCutPlaceBt.getPlateThickTo(), cutPlaceBt.getPlateThickFrom(),
                                cutPlaceBt.getPlateThickTo());
                        if (slabThickIntervalCheck) {
                            throw new CommonException("pm.cut_place_bt_001", cutPlaceBt.getPlateThickFrom(), cutPlaceBt.getPlateThickTo());
                        }
                    }

                }
            }

        }

        // 获取当前时间和用户名
        Date now = new Date();
        String username = DetailsHelper.getUserDetails().getUsername();
        List<PmCutPlaceBtTra> insertPmMoldSpecBtTraList = new ArrayList<>(pmCutPlaceBtList.size());

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

        // 记录更新操作的历史记录
        for (PmCutPlaceBt pmCutPlaceBt : updateList) {
            PmCutPlaceBtTra pmCutPlaceBtTra = new PmCutPlaceBtTra();
            BeanUtils.copyProperties(pmCutPlaceBt, pmCutPlaceBtTra);

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

        }
        // 先更新后插入
        pmCutPlaceBtRepository.batchUpdateByPrimaryKey(updateList);
        pmCutPlaceBtRepository.batchInsertSelective(insertList);

        // 记录插入操作的历史记录
        for (PmCutPlaceBt pmCutPlaceBt : insertList) {
            PmCutPlaceBtTra pmCutPlaceBtTra = new PmCutPlaceBtTra();
            BeanUtils.copyProperties(pmCutPlaceBt, pmCutPlaceBtTra);

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

        }
        // 执行批量插入操作
        pmCutPlaceBtTraRepository.batchInsertSelective(insertPmMoldSpecBtTraList);
    }

    private String getPlateFromKey(PmCutPlaceBt pmCutPlaceBt) {
        return pmCutPlaceBt.getFormPlateModeFirst() + "-" + pmCutPlaceBt.getRollLineNo();
    }

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

            // 获取当前时间和用户账号
            Date now = new Date();
            String username = DetailsHelper.getUserDetails().getUsername();
            List<PmCutPlaceBtTra> insertPmMoldSpecBtTraList = new ArrayList<>(pmCutPlaceBtList.size());
            for (PmCutPlaceBt pmCutPlaceBt : pmCutPlaceBtList) {
                PmCutPlaceBtTra pmCutPlaceBtTra = new PmCutPlaceBtTra();

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

            }
            // 插入履历表的删除记录
            pmCutPlaceBtTraRepository.batchInsertSelective(insertPmMoldSpecBtTraList);
        }
    }
}

