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.PmIngotSpecTrimBtService;
import com.xisc.pm.domain.entity.PmIngotSpecTrimBt;
import com.xisc.pm.domain.repository.PmIngotSpecTrimBtRepository;
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 org.springframework.beans.factory.annotation.Autowired;

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
 * @date 2024/12/9 16:55
 * @description
 */
@Slf4j
@ImportValidators({@ImportValidator(templateCode = "PM.INGOT_SPEC_TRIM_BT")})
public class PmIngotSpecTrimBtValidator extends BatchValidatorHandler {


    @Autowired
    private  ObjectMapper objectMapper;

    @Autowired
    private PmIngotSpecTrimBtRepository pmIngotSpecTrimBtRepository;

    @Autowired
    private PmIngotSpecTrimBtService pmIngotSpecTrimBtService;


    @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<PmIngotSpecTrimBt> list = new ArrayList<>(data.size());
        Map<PmIngotSpecTrimBt, Integer> idxMap = new HashMap<>(data.size());

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

                Integer integer = idxMap.putIfAbsent(pmIngotSpecTrimBt, i);
                if (integer != null && integer != i) {
                    // 重复数据
                    addErrorMsg(i, MessageAccessor.getMessage("pm.exist_same_data").getDesc());
                    continue;
                }
                list.add(pmIngotSpecTrimBt);
            } catch (JsonProcessingException e) {
                log.error(e.getMessage(), e);
            }
        }

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

        // 新增记录之间校验区间是否交叉
        Map<String, List<PmIngotSpecTrimBt>> pmIngotSpecTrimBtMap = list.stream()
                .collect(Collectors.groupingBy(pmIngotSpecTrimBtService::getTrimKey));
        for (Map.Entry<String, List<PmIngotSpecTrimBt>> entry : pmIngotSpecTrimBtMap.entrySet()) {
            List<PmIngotSpecTrimBt> ingotSpecTrimBtList = entry.getValue();
            for (int i = 0; i < ingotSpecTrimBtList.size() - 1; i++) {
                for (int j = i + 1; j < ingotSpecTrimBtList.size(); j++) {
                    // 校验轧制厚度区间是否交叉
                    boolean slabThickIntervalCheck = Utils.isIntersect(ingotSpecTrimBtList.get(i).getMinRollThick(),
                            ingotSpecTrimBtList.get(i).getMaxRollThick(), ingotSpecTrimBtList.get(j).getMinRollThick(),
                            ingotSpecTrimBtList.get(j).getMaxRollThick());
                    if (!slabThickIntervalCheck) {
                        continue;
                    }

                    // 校验轧制宽度区间是否交叉。
                    boolean rollWidthIntervalCheck = Utils.isIntersect(ingotSpecTrimBtList.get(i).getMinRollWidth(),
                            ingotSpecTrimBtList.get(i).getMaxRollWidth(), ingotSpecTrimBtList.get(j).getMinRollWidth(),
                            ingotSpecTrimBtList.get(j).getMaxRollWidth());
                    if (!rollWidthIntervalCheck) {
                        continue;
                    }

                    // 校验轧制长度区间是否交叉。
                    boolean rollLenIntervalCheck = Utils.isIntersect(ingotSpecTrimBtList.get(i).getRollLenFrom(),
                            ingotSpecTrimBtList.get(i).getRollLenTo(), ingotSpecTrimBtList.get(j).getRollLenFrom(),
                            ingotSpecTrimBtList.get(j).getRollLenTo());
                    if (!rollLenIntervalCheck) {
                        continue;
                    }
                    addErrorMsg(i, MessageAccessor.getMessage("pm.ignot_spec_trim_bt_001",
                            new Object[]{ingotSpecTrimBtList.get(j).getMinRollThick(), ingotSpecTrimBtList.get(j).getMaxRollThick(),
                                    ingotSpecTrimBtList.get(j).getMinRollWidth(), ingotSpecTrimBtList.get(j).getMaxRollWidth(),
                                    ingotSpecTrimBtList.get(j).getRollLenFrom(), ingotSpecTrimBtList.get(j).getRollLenTo()}).getDesc());
                    flag = false;
                }
            }
        }
        // 与数据库记录校验区间是否交叉
        List<String> ingotTypeList = list.stream().map(PmIngotSpecTrimBt::getIngotType).distinct().collect(Collectors.toList());
        List<String> guaranteeQualityList = list.stream().map(PmIngotSpecTrimBt::getGuaranteeQuality).distinct().collect(Collectors.toList());
        List<String> rollLineNoList = list.stream().map(PmIngotSpecTrimBt::getRollLineNo).distinct().collect(Collectors.toList());
        List<String> withSideFlagList = list.stream().map(PmIngotSpecTrimBt::getWithSideFlag).distinct().collect(Collectors.toList());
        List<String> rollDirectCodeList = list.stream().map(PmIngotSpecTrimBt::getRollDirectCode).distinct().collect(Collectors.toList());
        List<PmIngotSpecTrimBt> exisPmIngotSpecTrimBtList = pmIngotSpecTrimBtRepository.selectByCondition(Condition.builder(PmIngotSpecTrimBt.class)
                .andWhere(Sqls.custom().andIn(PmIngotSpecTrimBt.FIELD_INGOT_TYPE, ingotTypeList))
                .andWhere(Sqls.custom().andIn(PmIngotSpecTrimBt.FIELD_GUARANTEE_QUALITY, guaranteeQualityList))
                .andWhere(Sqls.custom().andIn(PmIngotSpecTrimBt.FIELD_ROLL_LINE_NO, rollLineNoList))
                .andWhere(Sqls.custom().andIn(PmIngotSpecTrimBt.FIELD_WITH_SIDE_FLAG, withSideFlagList))
                .andWhere(Sqls.custom().andIn(PmIngotSpecTrimBt.FIELD_ROLL_DIRECT_CODE, rollDirectCodeList))
                .andWhere(Sqls.custom().andEqualTo(PmIngotSpecTrimBt.FIELD_TENANT_ID, tenantId))
                .build());
        if (CollectionUtils.isNotEmpty(exisPmIngotSpecTrimBtList)) {
            Map<String, List<PmIngotSpecTrimBt>> existMap = exisPmIngotSpecTrimBtList.stream().collect(Collectors.groupingBy(pmIngotSpecTrimBtService::getTrimKey));
            for (int i = 0; i < list.size(); i++) {
                if (existMap.containsKey(pmIngotSpecTrimBtService.getTrimKey(list.get(i)))) {
                    List<PmIngotSpecTrimBt> existSpecTrimBtList = existMap.get(pmIngotSpecTrimBtService.getTrimKey(list.get(i)));
                    for (PmIngotSpecTrimBt ingotSpecTrimBt : existSpecTrimBtList) {
                        // 校验轧制厚度区间是否交叉
                        boolean rollThickIntervalCheck = Utils.isIntersect(list.get(i).getMinRollThick(),
                                list.get(i).getMaxRollThick(), ingotSpecTrimBt.getMinRollThick(),
                                ingotSpecTrimBt.getMaxRollThick());
                        if (!rollThickIntervalCheck) {
                            continue;
                        }

                        // 校验轧制宽度区间是否交叉
                        boolean rollWidthIntervalCheck = Utils.isIntersect(list.get(i).getMinRollWidth(),
                                list.get(i).getMaxRollWidth(), ingotSpecTrimBt.getMinRollWidth(),
                                ingotSpecTrimBt.getMaxRollWidth());
                        if (!rollWidthIntervalCheck) {
                            continue;
                        }

                        // 校验轧制长度区间是否交叉
                        boolean rollLenIntervalCheck = Utils.isIntersect(list.get(i).getRollLenFrom(),
                                list.get(i).getRollLenTo(), ingotSpecTrimBt.getRollLenFrom(),
                                ingotSpecTrimBt.getRollLenTo());
                        if (!rollLenIntervalCheck) {
                            continue;
                        }

                        addErrorMsg(i, MessageAccessor.getMessage("pm.ignot_spec_trim_bt_002",
                                new Object[]{ingotSpecTrimBt.getMinRollThick(), ingotSpecTrimBt.getMaxRollThick(),
                                        ingotSpecTrimBt.getMinRollWidth(), ingotSpecTrimBt.getMaxRollWidth(),
                                        ingotSpecTrimBt.getRollLenFrom(), ingotSpecTrimBt.getRollLenTo()}).getDesc());
                        flag = false;
                    }
                }
            }
        }
        return flag;
    }
}
