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

import com.xisc.pm.app.service.PmWmWwBtService;
import com.xisc.pm.domain.entity.PmWmWwBt;
import com.xisc.pm.domain.entity.PmWmWwBtTra;
import com.xisc.pm.domain.repository.PmWmWwBtRepository;
import com.xisc.pm.domain.repository.PmWmWwBtTraRepository;
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.helper.UniqueHelper;
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;

/**
 * 厚板产线_命令余材长度基准表(PmWmWwBt)应用服务
 *
 * @author 纪文桃 wentao.ji01@hand-china.com
 * @since 2024-08-15 15:18:30
 */
@Service
public class PmWmWwBtServiceImpl implements PmWmWwBtService {

    private PmWmWwBtRepository pmWmWwBtRepository;

    private PmWmWwBtTraRepository pmWmWwBtTraRepository;

    public PmWmWwBtServiceImpl(PmWmWwBtRepository pmWmWwBtRepository, PmWmWwBtTraRepository pmWmWwBtTraRepository) {
        this.pmWmWwBtRepository = pmWmWwBtRepository;
        this.pmWmWwBtTraRepository = pmWmWwBtTraRepository;
    }

    @Override
    public Page<PmWmWwBt> selectList(PageRequest pageRequest, PmWmWwBt pmWmWwBt) {
        return PageHelper.doPageAndSort(pageRequest, () -> pmWmWwBtRepository.selectList(pmWmWwBt));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveData(Long tenantId, List<PmWmWwBt> pmWmWwBtList) {
        for (PmWmWwBt pmWmWwBt : pmWmWwBtList) {
            //唯一性校验
            UniqueHelper.isUnique(pmWmWwBt);
            //单条记录中，“板坯宽度起”必须小于“板坯宽度止”；
            if (pmWmWwBt.getSlabWidthFrom() != null && pmWmWwBt.getSlabWidthTo() != null &&
                    pmWmWwBt.getSlabWidthFrom().compareTo(pmWmWwBt.getSlabWidthTo()) >= 0) {
                throw new CommonException("pm.wm_ww_bt_001");
            }
            //单条记录中，“板坯厚度起”必须小于“板坯厚度止”
            if (pmWmWwBt.getSlabThickFrom() != null && pmWmWwBt.getSlabThickTo() != null &&
                    pmWmWwBt.getSlabThickFrom().compareTo(pmWmWwBt.getSlabThickTo()) >= 0) {
                throw new CommonException("pm.wm_ww_bt_002");
            }
            //单条记录中，“无委充当板坯长度下限”必须小于“无委充当板坯长度上限”
            if (pmWmWwBt.getFillSlabLenMin() != null && pmWmWwBt.getFillSlabLenMax() != null &&
                    pmWmWwBt.getFillSlabLenMin().compareTo(pmWmWwBt.getFillSlabLenMax()) >= 0) {
                throw new CommonException("pm.wm_ww_bt_003");
            }
            //单条记录中，“请求外板坯长度下限”必须小于“请求外板坯长度上限”
            if (pmWmWwBt.getUnappSlabLenMin() != null && pmWmWwBt.getUnappSlabLenMax() != null &&
                    pmWmWwBt.getUnappSlabLenMin().compareTo(pmWmWwBt.getUnappSlabLenMax()) >= 0) {
                throw new CommonException("pm.wm_ww_bt_004");
            }
            //单条记录中，“轻压下CAST头部余材长度下限”必须小于“轻压下CAST头部余材长度上限”
            if (pmWmWwBt.getCastHeadLenMin() != null && pmWmWwBt.getCastHeadLenMax() != null &&
                    pmWmWwBt.getCastHeadLenMin().compareTo(pmWmWwBt.getCastHeadLenMax()) >= 0) {
                throw new CommonException("pm.pm.wm_ww_bt_005");
            }
            //单条记录中，“轻压下CAST尾部余材长度下限”必须小于“轻压下CAST尾部余材长度上限”
            if (pmWmWwBt.getCastTailLenMin() != null && pmWmWwBt.getCastTailLenMax() != null &&
                    pmWmWwBt.getCastTailLenMin().compareTo(pmWmWwBt.getCastTailLenMax()) >= 0) {
                throw new CommonException("pm.pm.wm_ww_bt_006");
            }
        }
        pmWmWwBtList.forEach(item -> item.setWholeBacklogCode("14"));

        // 3．唯一性索引：产线号、连铸机类型、板坯厚度起止区间、板坯宽度起止区间。更新/插入一条纪录时，在非区间索引相同的情况下，各区间至少有一项不存在交集，否则更新/插入失败。
        Map<String, List<PmWmWwBt>> pmWmWwBtMap = pmWmWwBtList.stream().collect(Collectors.groupingBy(this::getWmKey));
        for (Map.Entry<String, List<PmWmWwBt>> entry : pmWmWwBtMap.entrySet()) {
            List<PmWmWwBt> wmWwBtList = entry.getValue();
            for (int i = 0; i < wmWwBtList.size() - 1; i++) {
                for (int j = i + 1; j < wmWwBtList.size(); j++) {
                    // 校验板坯厚度区间是否交叉
                    boolean slabLenIntervalCheck = Utils.isIntersect(wmWwBtList.get(i).getSlabThickFrom(), wmWwBtList.get(i).getSlabThickTo(),
                            wmWwBtList.get(j).getSlabThickFrom(), wmWwBtList.get(j).getSlabThickTo());
                    if (!slabLenIntervalCheck) {
                        continue;
                    }

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

                    throw new CommonException("pm.wm_ww_bt_009", wmWwBtList.get(i).getSlabThickFrom(), wmWwBtList.get(i).getSlabThickTo(),
                            wmWwBtList.get(i).getSlabWidthFrom(), wmWwBtList.get(i).getSlabWidthTo());
                }
            }
        }

        // 与数据库记录校验
        List<String> mscLineNoList = pmWmWwBtList.stream().map(PmWmWwBt::getMscLineNo).distinct().collect(Collectors.toList());
        List<String> ccTypeList = pmWmWwBtList.stream().map(PmWmWwBt::getCcType).distinct().collect(Collectors.toList());
        List<Long> idList = pmWmWwBtList.stream().filter(item -> item.getId() != null).map(PmWmWwBt::getId).collect(Collectors.toList());
        List<PmWmWwBt> existWmWwBtList = pmWmWwBtRepository.selectByCondition(Condition.builder(PmWmWwBt.class)
                .andWhere(Sqls.custom().andIn(PmWmWwBt.FIELD_MSC_LINE_NO, mscLineNoList))
                .andWhere(Sqls.custom().andIn(PmWmWwBt.FIELD_CC_TYPE, ccTypeList))
                .andWhere(Sqls.custom().andEqualTo(PmWmWwBt.FIELD_TENANT_ID, tenantId))
                .andWhere(Sqls.custom().andNotIn(PmWmWwBt.FIELD_ID, idList, true))
                .build());
        if (CollectionUtils.isNotEmpty(existWmWwBtList)) {
            Map<String, List<PmWmWwBt>> existMap = existWmWwBtList.stream().collect(Collectors.groupingBy(this::getWmKey));
            for (PmWmWwBt pmWmWwBt : pmWmWwBtList) {
                if (existMap.containsKey(getWmKey(pmWmWwBt))) {
                    List<PmWmWwBt> wmWwBtList = existMap.get(getWmKey(pmWmWwBt));
                    for (PmWmWwBt wmWwBt : wmWwBtList) {
                        // 校验板坯厚度区间是否交叉
                        boolean slabLenIntervalCheck = Utils.isIntersect(pmWmWwBt.getSlabThickFrom(), pmWmWwBt.getSlabThickTo(),
                                wmWwBt.getSlabThickFrom(), wmWwBt.getSlabThickTo());
                        if (!slabLenIntervalCheck) {
                            continue;
                        }

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

                        throw new CommonException("pm.wm_ww_bt_010", wmWwBt.getSlabThickFrom(), wmWwBt.getSlabThickTo(),
                                wmWwBt.getSlabWidthFrom(), wmWwBt.getSlabWidthTo());
                    }
                }
            }
        }

        List<PmWmWwBt> insertList = pmWmWwBtList.stream().filter(line -> line.getId() == null).collect(Collectors.toList());
        List<PmWmWwBt> updateList = pmWmWwBtList.stream().filter(line -> line.getId() != null).collect(Collectors.toList());

        // 获取当前时间及操作人信息
        Date now = new Date();
        String username = DetailsHelper.getUserDetails().getUsername();
        List<PmWmWwBtTra> insertTraList = new ArrayList<>(insertList.size());
        // 记录历史表
        for (PmWmWwBt pmWmWwBt : updateList) {
            PmWmWwBtTra pmWmWwBtTra = new PmWmWwBtTra();
            BeanUtils.copyProperties(pmWmWwBt, pmWmWwBtTra);

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

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

        for (PmWmWwBt pmWmWwBt : insertList) {
            PmWmWwBtTra pmWmWwBtTra = new PmWmWwBtTra();
            BeanUtils.copyProperties(pmWmWwBt, pmWmWwBtTra);

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

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

    public String getWmKey(PmWmWwBt pmWmWwBt) {
        return pmWmWwBt.getMscLineNo() + pmWmWwBt.getCcType();
    }

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

            // 获取时间和当前操作人信息
            Date now = new Date();
            String username = DetailsHelper.getUserDetails().getUsername();
            List<PmWmWwBtTra> insertTraList = new ArrayList<>(pmWmWwBtList.size());
            for (PmWmWwBt pmWmWwBt : pmWmWwBtList) {
                PmWmWwBtTra pmWmWwBtTra = new PmWmWwBtTra();

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

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

