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.PmPlateThickAddvBtService;
import com.xisc.pm.domain.entity.PmPlateThickAddvBt;
import com.xisc.pm.domain.repository.PmPlateThickAddvBtRepository;
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 8:50
 * 已废弃
 */
@Slf4j
@ImportValidators({@ImportValidator(templateCode = "PM.PLATE_THICK_ADDV_BT")})
public class PmPlateThickAddvBtValidator extends BatchValidatorHandler {

    private final ObjectMapper objectMapper;

    private final PmPlateThickAddvBtRepository pmPlateThickAddvBtRepository;

    private final PmPlateThickAddvBtService pmPlateThickAddvBtService;

    public PmPlateThickAddvBtValidator(ObjectMapper objectMapper, PmPlateThickAddvBtRepository pmPlateThickAddvBtRepository, PmPlateThickAddvBtService pmPlateThickAddvBtService) {
        this.objectMapper = objectMapper;
        this.pmPlateThickAddvBtRepository = pmPlateThickAddvBtRepository;
        this.pmPlateThickAddvBtService = pmPlateThickAddvBtService;
    }


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

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

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

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

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

        // 校验钢板厚度
        Map<String, List<PmPlateThickAddvBt>> plateThickBtMap = list.stream().collect(Collectors.groupingBy(pmPlateThickAddvBtService::getPlateThickKey));
        for (Map.Entry<String, List<PmPlateThickAddvBt>> entry : plateThickBtMap.entrySet()) {
            List<PmPlateThickAddvBt> plateThickAddvBtList = entry.getValue();
            for (int i = 0; i < plateThickAddvBtList.size() - 1; i++) {
                for (int j = i + 1; j < plateThickAddvBtList.size(); j++) {
                    // 校验钢板厚度区间是否交叉
                    boolean slabThickIntervalCheck = Utils.isIntersect(plateThickAddvBtList.get(i).getPlateThickFrom(), plateThickAddvBtList.get(i).getPlateThickTo(),
                            plateThickAddvBtList.get(j).getPlateThickFrom(), plateThickAddvBtList.get(j).getPlateThickTo());
                    if (slabThickIntervalCheck) {
                        addErrorMsg(idxMap.get(list.get(i)), MessageAccessor.getMessage("pm.cut_place_bt_001", new Object[]{plateThickAddvBtList.get(j).getPlateThickFrom(), plateThickAddvBtList.get(j).getPlateThickTo()}).getDesc());
                        flag = false;
                    }

                }
            }
        }

        // 校验组合板宽度
        Map<String, List<PmPlateThickAddvBt>> combinePlateWidthBtMap = list.stream().collect(Collectors.groupingBy(pmPlateThickAddvBtService::getCombinePlateWidthKey));
        for (Map.Entry<String, List<PmPlateThickAddvBt>> entry : combinePlateWidthBtMap.entrySet()) {
            List<PmPlateThickAddvBt> plateThickAddvBtList = entry.getValue();
            for (int i = 0; i < plateThickAddvBtList.size() - 1; i++) {
                for (int j = i + 1; j < plateThickAddvBtList.size(); j++) {
                    // 校验组合板宽度区间是否交叉
                    boolean combinePlateWidthIntervalCheck = Utils.isIntersect(plateThickAddvBtList.get(i).getCombinePlateWidthFrom(),
                            plateThickAddvBtList.get(i).getCombinePlateWidthTo(), plateThickAddvBtList.get(j).getCombinePlateWidthFrom(),
                            plateThickAddvBtList.get(j).getCombinePlateWidthTo());
                    if (combinePlateWidthIntervalCheck) {
                        addErrorMsg(idxMap.get(list.get(i)), MessageAccessor.getMessage("pm.plate_spec_yield_bt", new Object[]{plateThickAddvBtList.get(j).getCombinePlateWidthFrom(), plateThickAddvBtList.get(j).getCombinePlateWidthTo()}).getDesc());
                        flag = false;
                    }

                }
            }
        }

        List<String> stCodeList = list.stream().map(PmPlateThickAddvBt::getStCode).distinct().collect(Collectors.toList());
        List<String> formPlateModeList = list.stream().map(PmPlateThickAddvBt::getFormPlateMode).distinct().collect(Collectors.toList());
        List<String> adTypeModeList = list.stream().map(PmPlateThickAddvBt::getAdTypeMode).distinct().collect(Collectors.toList());
        List<String> rollDirectCodeList = list.stream().map(PmPlateThickAddvBt::getRollDirectCode).distinct().collect(Collectors.toList());
        List<String> rollModeList = list.stream().map(PmPlateThickAddvBt::getRollMode).distinct().collect(Collectors.toList());
        List<String> heatTreatModeList = list.stream().map(PmPlateThickAddvBt::getHeatTreatMode).distinct().collect(Collectors.toList());
        List<String> rollLineNoList = list.stream().map(PmPlateThickAddvBt::getRollLineNo).distinct().collect(Collectors.toList());
        List<PmPlateThickAddvBt> existPlateThickAddvBtList = pmPlateThickAddvBtRepository.selectByCondition(Condition.builder(PmPlateThickAddvBt.class)
                .andWhere(Sqls.custom().andEqualTo(PmPlateThickAddvBt.FIELD_TENANT_ID, tenantId))
                .andWhere(Sqls.custom().andIn(PmPlateThickAddvBt.FIELD_ST_CODE, stCodeList))
                .andWhere(Sqls.custom().andIn(PmPlateThickAddvBt.FIELD_FORM_PLATE_MODE, formPlateModeList))
                .andWhere(Sqls.custom().andIn(PmPlateThickAddvBt.FIELD_AD_TYPE_MODE, adTypeModeList))
                .andWhere(Sqls.custom().andIn(PmPlateThickAddvBt.FIELD_ROLL_DIRECT_CODE, rollDirectCodeList))
                .andWhere(Sqls.custom().andIn(PmPlateThickAddvBt.FIELD_ROLL_MODE, rollModeList))
                .andWhere(Sqls.custom().andIn(PmPlateThickAddvBt.FIELD_HEAT_TREAT_MODE, heatTreatModeList))
                .andWhere(Sqls.custom().andIn(PmPlateThickAddvBt.FIELD_ROLL_LINE_NO, rollLineNoList))
                .build());

        if (CollectionUtils.isNotEmpty(existPlateThickAddvBtList)) {
            // 校验钢板厚度
            Map<String, List<PmPlateThickAddvBt>> existPlateThickBtMap = existPlateThickAddvBtList.stream().collect(Collectors.groupingBy(pmPlateThickAddvBtService::getPlateThickKey));
            // 校验组合板宽度
            Map<String, List<PmPlateThickAddvBt>> existCombinePlateWidthBtMap = existPlateThickAddvBtList.stream().collect(Collectors.groupingBy(pmPlateThickAddvBtService::getCombinePlateWidthKey));
            for (int i = 0; i < list.size(); i++) {
                // 校验钢板厚度区间是否交叉
                if (existPlateThickBtMap.containsKey(pmPlateThickAddvBtService.getPlateThickKey(list.get(i)))) {
                    List<PmPlateThickAddvBt> plateThickAddvBtList = existPlateThickBtMap.get(pmPlateThickAddvBtService.getPlateThickKey(list.get(i)));
                    for (PmPlateThickAddvBt existPlateThickAddvBt : plateThickAddvBtList) {
                        boolean slabThickIntervalCheck = Utils.isIntersect(list.get(i).getPlateThickFrom(), list.get(i).getPlateThickTo(),
                                existPlateThickAddvBt.getPlateThickFrom(), existPlateThickAddvBt.getPlateThickTo());
                        if (slabThickIntervalCheck) {
                            addErrorMsg(idxMap.get(list.get(i)), MessageAccessor.getMessage("pm.cut_place_bt_001", new Object[]{existPlateThickAddvBt.getPlateThickFrom(), existPlateThickAddvBt.getPlateThickTo()}).getDesc());
                            flag = false;
                        }
                    }
                }
                // 校验组合板宽度是否交叉
                if (existCombinePlateWidthBtMap.containsKey(pmPlateThickAddvBtService.getCombinePlateWidthKey(list.get(i)))) {
                    List<PmPlateThickAddvBt> plateThickAddvBtList = existCombinePlateWidthBtMap.get(pmPlateThickAddvBtService.getCombinePlateWidthKey(list.get(i)));
                    for (PmPlateThickAddvBt existPlateThickAddvBt : plateThickAddvBtList) {
                        boolean combinePlateWidthIntervalCheck = Utils.isIntersect(list.get(i).getCombinePlateWidthFrom(),
                                list.get(i).getCombinePlateWidthTo(), existPlateThickAddvBt.getCombinePlateWidthFrom(),
                                existPlateThickAddvBt.getCombinePlateWidthTo());
                        if (combinePlateWidthIntervalCheck) {
                            addErrorMsg(idxMap.get(list.get(i)), MessageAccessor.getMessage("pm.plate_spec_yield_bt", new Object[]{existPlateThickAddvBt.getCombinePlateWidthFrom(), existPlateThickAddvBt.getCombinePlateWidthTo()}).getDesc());
                            flag = false;
                        }
                    }
                }

            }
        }
        return flag;
    }
}
