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

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.xisc.pm.app.service.PmPlateTrimBtService;
import com.xisc.pm.domain.entity.PmPlateTrimBt;
import com.xisc.pm.domain.repository.PmPlateTrimBtRepository;
import com.xisc.pm.infra.util.Utils;
import io.choerodon.core.exception.CommonException;
import io.choerodon.core.oauth.DetailsHelper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.hzero.boot.imported.app.service.BatchValidatorHandler;
import org.hzero.boot.imported.infra.validator.annotation.ImportValidator;
import org.hzero.boot.imported.infra.validator.annotation.ImportValidators;
import org.hzero.core.message.MessageAccessor;
import org.hzero.mybatis.domian.Condition;
import org.hzero.mybatis.util.Sqls;

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

/**
 * @author 纪文桃 wentao.ji01@hand-china.com
 * @since 2024/7/26 10:03
 */
@Slf4j
@ImportValidators({@ImportValidator(templateCode = "PM.PLATE_TRIM_BT")})
public class PmPlateTrimBtValidator extends BatchValidatorHandler {
    private final ObjectMapper objectMapper;

    private final PmPlateTrimBtRepository pmPlateTrimBtRepository;

    private final PmPlateTrimBtService pmPlateTrimBtService;

    public PmPlateTrimBtValidator(ObjectMapper objectMapper, PmPlateTrimBtRepository pmPlateTrimBtRepository, PmPlateTrimBtService pmPlateTrimBtService) {
        this.objectMapper = objectMapper;
        this.pmPlateTrimBtRepository = pmPlateTrimBtRepository;
        this.pmPlateTrimBtService = pmPlateTrimBtService;
    }


    @Override
    public boolean validate(List<String> data) {
        if (CollectionUtils.isEmpty(data)) {
            throw new CommonException("pm.import_data_is_empty_list");
        }
        boolean flag = true;
        Long tenantId = 0L;
        if (DetailsHelper.getUserDetails() != null && DetailsHelper.getUserDetails().getTenantId() != null) {
            tenantId = DetailsHelper.getUserDetails().getTenantId();
        }
        List<PmPlateTrimBt> list = new ArrayList<>(data.size());
        Map<PmPlateTrimBt, Integer> idxMap = new HashMap<>(data.size());

        for (int i = 0; i < data.size(); i++) {
            try {
                // 转换对象
                PmPlateTrimBt pmPlateTrimBt = objectMapper.readValue(data.get(i), PmPlateTrimBt.class);
                pmPlateTrimBt.setTenantId(tenantId);

                Integer integer = idxMap.putIfAbsent(pmPlateTrimBt, i);
                if (integer != null && integer != i) {
                    // 重复数据
                    addErrorMsg(i, MessageAccessor.getMessage("pm.exist_same_data").getDesc());
                    continue;
                }

                list.add(pmPlateTrimBt);
            } catch (JsonProcessingException e) {
                log.error(e.getMessage(), e);
            }
        }

        // 如果集合为空，则结束
        if (CollectionUtils.isEmpty(list)) {
            return true;
        }

        // 新增记录之间校验区间是否交叉
        Map<String, List<PmPlateTrimBt>> plateFromMap = list.stream().collect(Collectors.groupingBy(pmPlateTrimBtService::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;
                    }
                    addErrorMsg(idxMap.get(pdTmpYieldBtList.get(i)), MessageAccessor.getMessage("pm.plate_trim_bt",
                            new Object[]{  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()}).getDesc());
                    flag = false;
                }
            }
        }

        // 与数据库记录校验区间是否交叉
        List<String> wideSideFlagList = list.stream().map(PmPlateTrimBt::getWithSideFlag).distinct().collect(Collectors.toList());
        List<String> rollineNoList = list.stream().map(PmPlateTrimBt::getMscLineNo).distinct().collect(Collectors.toList());
        List<Long> idList = list.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 (org.apache.commons.collections.CollectionUtils.isNotEmpty(existPmPlateTrimBtList)) {
            Map<String, List<PmPlateTrimBt>> existMap = existPmPlateTrimBtList.stream().collect(Collectors.groupingBy(pmPlateTrimBtService::getTmpKey));
            for (int i = 0; i < list.size(); i ++) {
                if (existMap.containsKey(pmPlateTrimBtService.getTmpKey(list.get(i)))) {
                    List<PmPlateTrimBt> plateTrimBtList = existMap.get(pmPlateTrimBtService.getTmpKey(list.get(i)));
                    for (PmPlateTrimBt plateTrimBt : plateTrimBtList) {
                        // 校验钢板厚度区间是否交叉
                        boolean plateThickIntervalCheck = Utils.isIntersect(list.get(i).getPlateThickFrom(),
                                list.get(i).getPlateThickTo(), plateTrimBt.getPlateThickFrom(),
                                plateTrimBt.getPlateThickTo());
                        if (!plateThickIntervalCheck) {
                            continue;
                        }
                        // 校验组合板宽度区间是否交叉
                        boolean combinePlateWidthIntervalCheck = Utils.isIntersect(list.get(i).getCombinePlateWidthFrom(),
                                list.get(i).getCombinePlateWidthTo(), plateTrimBt.getCombinePlateWidthFrom(),
                                plateTrimBt.getCombinePlateWidthTo());
                        if (!combinePlateWidthIntervalCheck) {
                            continue;
                        }
                        // 校验小板长度区间是否交叉
                        boolean smallPlateLenIntervalCheck = Utils.isIntersect(list.get(i).getSmallPlateLenFrom(),
                                list.get(i).getSmallPlateLenTo(), plateTrimBt.getSmallPlateLenFrom(),
                                plateTrimBt.getSmallPlateLenTo());
                        if (!smallPlateLenIntervalCheck) {
                            continue;
                        }
                        // 校验展宽比区间是否交叉
                        boolean widenIntervalCheck = Utils.isIntersect(list.get(i).getWidenFrom(), list.get(i).getWidenTo(),
                                plateTrimBt.getWidenFrom(), plateTrimBt.getWidenTo());
                        if (!widenIntervalCheck) {
                            continue;
                        }
                        addErrorMsg(i, MessageAccessor.getMessage("pm.plate_trim_bt_001",
                                new Object[]{  plateTrimBt.getPlateThickFrom(), plateTrimBt.getPlateThickTo(),
                                        plateTrimBt.getCombinePlateWidthFrom(), plateTrimBt.getCombinePlateWidthTo(),
                                        plateTrimBt.getSmallPlateLenFrom(), plateTrimBt.getSmallPlateLenTo(),
                                        plateTrimBt.getWidenFrom(), plateTrimBt.getWidenTo()}).getDesc());
                        flag = false;

                    }
                }
            }
        }
        return flag;
    }
}
