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

import com.xisc.pm.api.dto.export.PmPlateTrimBtDTO;
import com.xisc.pm.app.service.PmPlateTrimBtService;
import com.xisc.pm.domain.entity.PmPlateTrimBt;
import com.xisc.pm.domain.entity.PmPlateTrimBtTra;
import com.xisc.pm.domain.repository.PmPlateTrimBtRepository;
import com.xisc.pm.domain.repository.PmPlateTrimBtTraRepository;
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;

/**
 * 钢板切边量基准表(PmPlateTrimBt)应用服务
 *
 * @author 纪文桃 wentao.ji01@hand-china.com
 * @since 2024-07-24 10:37:38
 */
@Service
public class PmPlateTrimBtServiceImpl implements PmPlateTrimBtService {

    private PmPlateTrimBtRepository pmPlateTrimBtRepository;

    private PmPlateTrimBtTraRepository pmPlateTrimBtTraRepository;

    private LovAdapter lovAdapter;

    public PmPlateTrimBtServiceImpl(PmPlateTrimBtRepository pmPlateTrimBtRepository, PmPlateTrimBtTraRepository pmPlateTrimBtTraRepository, LovAdapter lovAdapter) {
        this.pmPlateTrimBtRepository = pmPlateTrimBtRepository;
        this.pmPlateTrimBtTraRepository = pmPlateTrimBtTraRepository;
        this.lovAdapter = lovAdapter;
    }

    @Override
    public Page<PmPlateTrimBt> selectList(PageRequest pageRequest, PmPlateTrimBt pmPlateTrimBt) {
        return PageHelper.doPageAndSort(pageRequest, () -> pmPlateTrimBtRepository.selectList(pmPlateTrimBt));
    }

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

        // 新增记录之间校验区间是否交叉
        Map<String, List<PmPlateTrimBt>> plateFromMap = pmPlateTrimBtList.stream().collect(Collectors.groupingBy(this::getTmpKey));
        for (Map.Entry<String, List<PmPlateTrimBt>> entry : plateFromMap.entrySet()) {
            List<PmPlateTrimBt> 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 slabThickIntervalCheck = Utils.isIntersect(pdTmpYieldBtList.get(i).getCombinePlateWidthFrom(),
                            pdTmpYieldBtList.get(i).getCombinePlateWidthTo(), pdTmpYieldBtList.get(j).getCombinePlateWidthFrom(),
                            pdTmpYieldBtList.get(j).getCombinePlateWidthTo());
                    if (!slabThickIntervalCheck) {
                        continue;
                    }

                    // 校验小板长度区间是否交叉
                    boolean smallPlateLenIntervalCheck = Utils.isIntersect(pdTmpYieldBtList.get(i).getSmallPlateLenFrom(),
                            pdTmpYieldBtList.get(i).getSmallPlateLenTo(), pdTmpYieldBtList.get(j).getSmallPlateLenFrom(),
                            pdTmpYieldBtList.get(j).getSmallPlateLenTo());
                    if (!smallPlateLenIntervalCheck) {
                        continue;
                    }

                    // 校验展宽比区间是否交叉
                    boolean widenIntervalCheck = Utils.isIntersect(pdTmpYieldBtList.get(i).getWidenFrom(), pdTmpYieldBtList.get(i).getWidenTo(),
                            pdTmpYieldBtList.get(j).getWidenFrom(), pdTmpYieldBtList.get(j).getWidenTo());
                    if (!widenIntervalCheck) {
                        continue;
                    }

                    throw new CommonException("pm.plate_trim_bt",
                            pdTmpYieldBtList.get(j).getPlateThickFrom(), pdTmpYieldBtList.get(j).getPlateThickTo(),
                            pdTmpYieldBtList.get(j).getCombinePlateWidthFrom(), pdTmpYieldBtList.get(j).getCombinePlateWidthTo(),
                            pdTmpYieldBtList.get(j).getSmallPlateLenFrom(), pdTmpYieldBtList.get(j).getSmallPlateLenTo(),
                            pdTmpYieldBtList.get(j).getWidenFrom(), pdTmpYieldBtList.get(j).getWidenTo());
                }
            }
        }
        // 与数据库记录校验区间是否交叉
        List<String> wideSideFlagList = pmPlateTrimBtList.stream().map(PmPlateTrimBt::getWithSideFlag).distinct().collect(Collectors.toList());
        List<String> rollineNoList = pmPlateTrimBtList.stream().map(PmPlateTrimBt::getMscLineNo).distinct().collect(Collectors.toList());
        List<Long> idList = pmPlateTrimBtList.stream().filter(item -> item.getPptbId() != null).map(PmPlateTrimBt::getPptbId).collect(Collectors.toList());
        List<PmPlateTrimBt> existPmPlateTrimBtList = pmPlateTrimBtRepository.selectByCondition(Condition.builder(PmPlateTrimBt.class)
                .andWhere(Sqls.custom().andIn(PmPlateTrimBt.FIELD_WITH_SIDE_FLAG, wideSideFlagList))
                .andWhere(Sqls.custom().andIn(PmPlateTrimBt.FIELD_MSC_LINE_NO, rollineNoList))
                .andWhere(Sqls.custom().andEqualTo(PmPlateTrimBt.FIELD_TENANT_ID, tenantId))
                .andWhere(Sqls.custom().andNotIn(PmPlateTrimBt.FIELD_PPTB_ID, idList, true))
                .build());
        if (CollectionUtils.isNotEmpty(existPmPlateTrimBtList)) {
            Map<String, List<PmPlateTrimBt>> existMap = existPmPlateTrimBtList.stream().collect(Collectors.groupingBy(this::getTmpKey));
            for (PmPlateTrimBt pmPlateTrimBt : pmPlateTrimBtList) {
                if (existMap.containsKey(getTmpKey(pmPlateTrimBt))) {
                    List<PmPlateTrimBt> plateTrimBtList = existMap.get(getTmpKey(pmPlateTrimBt));
                    for (PmPlateTrimBt plateTrimBt : plateTrimBtList) {
                        // 校验钢板厚度区间是否交叉
                        boolean plateThickIntervalCheck = Utils.isIntersect(pmPlateTrimBt.getPlateThickFrom(),
                                pmPlateTrimBt.getPlateThickTo(), plateTrimBt.getPlateThickFrom(),
                                plateTrimBt.getPlateThickTo());
                        if (!plateThickIntervalCheck) {
                            continue;
                        }
                        // 校验组合板宽度区间是否交叉
                        boolean combinePlateWidthIntervalCheck = Utils.isIntersect(pmPlateTrimBt.getCombinePlateWidthFrom(),
                                pmPlateTrimBt.getCombinePlateWidthTo(), plateTrimBt.getCombinePlateWidthFrom(),
                                plateTrimBt.getCombinePlateWidthTo());
                        if (!combinePlateWidthIntervalCheck) {
                            continue;
                        }
                        // 校验小板长度区间是否交叉
                        boolean smallPlateLenIntervalCheck = Utils.isIntersect(pmPlateTrimBt.getSmallPlateLenFrom(),
                                pmPlateTrimBt.getSmallPlateLenTo(), plateTrimBt.getSmallPlateLenFrom(),
                                plateTrimBt.getSmallPlateLenTo());
                        if (!smallPlateLenIntervalCheck) {
                            continue;
                        }
                        // 校验展宽比区间是否交叉
                        boolean widenIntervalCheck = Utils.isIntersect(pmPlateTrimBt.getWidenFrom(), pmPlateTrimBt.getWidenTo(),
                                plateTrimBt.getWidenFrom(), plateTrimBt.getWidenTo());
                        if (!widenIntervalCheck) {
                            continue;
                        }
                        throw new CommonException("pm.plate_trim_bt_001",
                                plateTrimBt.getPlateThickFrom(), plateTrimBt.getPlateThickTo(),
                                plateTrimBt.getCombinePlateWidthFrom(), plateTrimBt.getCombinePlateWidthTo(),
                                plateTrimBt.getSmallPlateLenFrom(), plateTrimBt.getSmallPlateLenTo(),
                                plateTrimBt.getWidenFrom(), plateTrimBt.getWidenTo());

                    }
                }
            }
        }


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

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

        // 记录历史表
        for (PmPlateTrimBt pmPlateTrimBt : updateList) {
            PmPlateTrimBtTra pmPlateTrimBtTra = new PmPlateTrimBtTra();
            BeanUtils.copy(pmPlateTrimBt, pmPlateTrimBtTra);

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

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

        for (PmPlateTrimBt pmPlateTrimBt : insertList) {
            PmPlateTrimBtTra pmPlateTrimBtTra = new PmPlateTrimBtTra();
            BeanUtils.copy(pmPlateTrimBt, pmPlateTrimBtTra);

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

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

    @Override
    public String getTmpKey(PmPlateTrimBt pmPlateTrimBt) {
        return pmPlateTrimBt.getWithSideFlag() + pmPlateTrimBt.getMscLineNo();
    }

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

            // 获取时间和当前操作人信息
            Date now = new Date();
            String username = DetailsHelper.getUserDetails().getUsername();
            List<PmPlateTrimBtTra> insertPmMoldSpecBtTraList = new ArrayList<>(pmPlateTrimBtList.size());
            for (PmPlateTrimBt pmPlateTrimBt : pmPlateTrimBtList) {
                PmPlateTrimBtTra pmPlateTrimBtTra = new PmPlateTrimBtTra();

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

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

    @Override
    public List<PmPlateTrimBtDTO> exportList(PmPlateTrimBt pmPlateTrimBt) {
        List<PmPlateTrimBt> pmPlateTrimBtList = pmPlateTrimBtRepository.selectList(pmPlateTrimBt);
        // 如果集合为空，则返回
        if (CollectionUtils.isEmpty(pmPlateTrimBtList)) {
            return Collections.emptyList();
        }
        // 获取切边标记含义
        List<LovValueDTO> withSideFlagList = lovAdapter.queryLovValue(Constants.LovCode.WITH_SIDE_FLAG, pmPlateTrimBt.getTenantId());
        // 设计产线号含义
        List<LovValueDTO> mscLineNoList = lovAdapter.queryLovValue(Constants.LovCode.MSC_LINE_NO, pmPlateTrimBt.getTenantId());

        Map<String, String> withSideFlagLovMap = new HashMap<>(withSideFlagList.size());
        Map<String, String> rollLineNoLovMap = new HashMap<>(mscLineNoList.size());

        // 赋值
        if (CollectionUtils.isNotEmpty(withSideFlagList)) {
            withSideFlagLovMap = withSideFlagList.stream().collect(Collectors.toMap(LovValueDTO::getValue, LovValueDTO::getMeaning));
        }

        if (CollectionUtils.isNotEmpty(mscLineNoList)) {
            rollLineNoLovMap = mscLineNoList.stream().collect(Collectors.toMap(LovValueDTO::getValue, LovValueDTO::getMeaning));
        }

        List<PmPlateTrimBtDTO> resultList = new ArrayList<>(pmPlateTrimBtList.size());
        for (PmPlateTrimBt line : pmPlateTrimBtList) {
            if (!withSideFlagLovMap.isEmpty()) {
                line.setWithSideFlagDesc(withSideFlagLovMap.getOrDefault(line.getWithSideFlag(), ""));
            }

            if (!rollLineNoLovMap.isEmpty()) {
                line.setMscLineNoDesc(rollLineNoLovMap.getOrDefault(line.getMscLineNo(), ""));
            }
            PmPlateTrimBtDTO pmPlateTrimBtDTO = new PmPlateTrimBtDTO();
            BeanUtils.copy(line, pmPlateTrimBtDTO);
            resultList.add(pmPlateTrimBtDTO);

        }
        return resultList;
    }
}

