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

import com.xisc.pm.app.service.PmMinThickTolBtService;
import com.xisc.pm.domain.entity.PmMinThickTolBt;
import com.xisc.pm.domain.entity.PmMinThickTolBtTra;
import com.xisc.pm.domain.repository.PmMinThickTolBtRepository;
import com.xisc.pm.domain.repository.PmMinThickTolBtTraRepository;
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;

/**
 * 最小轧制厚度公差范围基准表(PmMinThickTolBt)应用服务
 *
 * @author 纪文桃 wentao.ji01@hand-china.com
 * @since 2024-07-23 11:11:39
 */
@Service
public class PmMinThickTolBtServiceImpl implements PmMinThickTolBtService {

    private PmMinThickTolBtRepository pmMinThickTolBtRepository;

    private PmMinThickTolBtTraRepository pmMinThickTolBtTraRepository;

    public PmMinThickTolBtServiceImpl(PmMinThickTolBtRepository pmMinThickTolBtRepository, PmMinThickTolBtTraRepository pmMinThickTolBtTraRepository) {
        this.pmMinThickTolBtRepository = pmMinThickTolBtRepository;
        this.pmMinThickTolBtTraRepository = pmMinThickTolBtTraRepository;
    }

    @Override
    public Page<PmMinThickTolBt> selectList(PageRequest pageRequest, PmMinThickTolBt pmMinThickTolBt) {
        return PageHelper.doPageAndSort(pageRequest, () -> pmMinThickTolBtRepository.selectList(pmMinThickTolBt));
    }

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

        // 唯一性索引：钢板厚度起止区间、轧制产线号。更新/插入一条纪录时，在非区间索引相同的情况下，各区间至少有一项不存在交集，否则更新/插入失败。
        // 新增记录之间校验区间是否交叉-其他条件相同时，判断钢板厚度
        Map<String, List<PmMinThickTolBt>> pmMinThickTolBtMap = pmMinThickTolBtList.stream()
                .collect(Collectors.groupingBy(this::getPmMinThickTolBtKey));
        for (Map.Entry<String, List<PmMinThickTolBt>> entry : pmMinThickTolBtMap.entrySet()) {
            List<PmMinThickTolBt> minThickTolBtList = entry.getValue();
            for (int i = 0; i < minThickTolBtList.size() - 1; i++) {
                for (int j = i + 1; j < minThickTolBtList.size(); j++) {
                    // 校验钢板厚度区间是否交叉
                    boolean slabThickIntervalCheck = Utils.isIntersect(minThickTolBtList.get(i).getPlateThickFrom(), minThickTolBtList.get(i).getPlateThickTo(),
                            minThickTolBtList.get(j).getPlateThickFrom(), minThickTolBtList.get(j).getPlateThickTo());
                    if (slabThickIntervalCheck) {
                        throw new CommonException("pm.cut_place_bt_001",minThickTolBtList.get(j).getPlateThickFrom(), minThickTolBtList.get(j).getPlateThickTo());
                    }
                }
            }
        }

        // 校验数据是否符合规则
        List<String> rollLineNoList = pmMinThickTolBtList.stream().map(PmMinThickTolBt::getRollLineNo).distinct().collect(Collectors.toList());
        List<Long> idList = pmMinThickTolBtList.stream().filter(item -> item.getPmttbId() != null).map(PmMinThickTolBt::getPmttbId).collect(Collectors.toList());
        List<PmMinThickTolBt> existPmMinThickTolBtList = pmMinThickTolBtRepository.selectByCondition(Condition.builder(PmMinThickTolBt.class)
                .andWhere(Sqls.custom().andEqualTo(PmMinThickTolBt.FIELD_TENANT_ID, tenantId))
                .andWhere(Sqls.custom().andIn(PmMinThickTolBt.FIELD_ROLL_LINE_NO, rollLineNoList))
                .andWhere(Sqls.custom().andNotIn(PmMinThickTolBt.FIELD_PMTTB_ID, idList, true))
                .build());
        // 与数据库记录校验区间是否交叉
        if (CollectionUtils.isNotEmpty(existPmMinThickTolBtList)) {
            Map<String, List<PmMinThickTolBt>> existPmMinThickTolBtMap = existPmMinThickTolBtList.stream()
                    .collect(Collectors.groupingBy(this::getPmMinThickTolBtKey));
            // 遍历新增更新的list
            for (PmMinThickTolBt pmMinThickTolBt : pmMinThickTolBtList) {
                // 如果数据库数据存在该条记录，则判断区间是否交叉
                if (existPmMinThickTolBtMap.containsKey(getPmMinThickTolBtKey(pmMinThickTolBt))) {
                    List<PmMinThickTolBt> minThickTolBtList = existPmMinThickTolBtMap.get(getPmMinThickTolBtKey(pmMinThickTolBt));
                    for (PmMinThickTolBt existMinThickTolBt : minThickTolBtList) {
                        // 校验钢板厚度区间是否交叉
                        boolean slabThickIntervalCheck = Utils.isIntersect(pmMinThickTolBt.getPlateThickFrom(),
                                pmMinThickTolBt.getPlateThickTo(), existMinThickTolBt.getPlateThickFrom(),
                                existMinThickTolBt.getPlateThickTo());
                        if (slabThickIntervalCheck) {
                            throw new CommonException("pm.cut_place_bt_006", existMinThickTolBt.getPlateThickFrom(),
                                    existMinThickTolBt.getPlateThickTo());
                        }
                    }
                }
            }
        }

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

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

        // 记录历史表
        for (PmMinThickTolBt pmMinThickTolBt : updateList) {
            PmMinThickTolBtTra pmMinThickTolBtTra = new PmMinThickTolBtTra();
            BeanUtils.copyProperties(pmMinThickTolBt, pmMinThickTolBtTra);

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

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

        for (PmMinThickTolBt pmMinThickTolBt : insertList) {
            PmMinThickTolBtTra pmMinThickTolBtTra = new PmMinThickTolBtTra();
            BeanUtils.copyProperties(pmMinThickTolBt, pmMinThickTolBtTra);

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

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

    private String getPmMinThickTolBtKey(PmMinThickTolBt pmMinThickTolBt) {
        return pmMinThickTolBt.getRollLineNo();
    }

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

            // 获取时间和当前操作人信息
            Date now = new Date();
            String username = DetailsHelper.getUserDetails().getUsername();
            List<PmMinThickTolBtTra> insertPmMoldSpecBtTraList = new ArrayList<>(pmMinThickTolBtList.size());
            for (PmMinThickTolBt pmMinThickTolBt : pmMinThickTolBtList) {
                PmMinThickTolBtTra pmMinThickTolBtTra = new PmMinThickTolBtTra();

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

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

