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

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.xisc.pm.domain.entity.PmMoldSpecBt;
import com.xisc.pm.domain.repository.PmMoldSpecBtRepository;
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.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author 纪文桃 wentao.ji01@hand-china.com
 * @since 2024/9/25 14:32
 */
@Slf4j
@ImportValidators({@ImportValidator(templateCode = "PM.MOLD_SPEC_BT")})
public class PmMoldSpecBtValidator extends BatchValidatorHandler {

    private final ObjectMapper objectMapper;

    private final PmMoldSpecBtRepository pmMoldSpecBtRepository;

    public PmMoldSpecBtValidator(ObjectMapper objectMapper, PmMoldSpecBtRepository pmMoldSpecBtRepository) {
        this.objectMapper = objectMapper;
        this.pmMoldSpecBtRepository = pmMoldSpecBtRepository;
    }

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

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

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

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

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

        // 校验新增更新的数据之间是否重复
        Map<String, List<PmMoldSpecBt>> pmMoldSpecBtMap = list.stream().collect(Collectors.groupingBy(pmMoldSpecBt ->
                pmMoldSpecBt.getCcType() + "-" + pmMoldSpecBt.getCastThick() + "-" + pmMoldSpecBt.getCastWidth() + "-"
                        + pmMoldSpecBt.getMscLineNo()));

        for (int i = 0; i < list.size(); i++) {
            if (pmMoldSpecBtMap.get(list.get(i).getCcType() + "-" + list.get(i).getCastThick() + "-" + list.get(i).getCastWidth() + "-"
                    + list.get(i).getMscLineNo()).size() > 1) {
                addErrorMsg(i, MessageAccessor.getMessage("pm.mold_spec_bt_002",
                        new Object[]{list.get(i).getCcType(), list.get(i).getCastThick(), list.get(i).getCastWidth(),
                                list.get(i).getMscLineNo()}).getDesc());
                flag = false;
            }
        }

        // 获取字段集合，查询数据库该范围内数据
        List<String> ccTypeList = list.stream().map(PmMoldSpecBt::getCcType).distinct().collect(Collectors.toList());
        List<BigDecimal> castThickList = list.stream().map(PmMoldSpecBt::getCastThick).distinct().collect(Collectors.toList());
        List<BigDecimal> castWidthList = list.stream().map(PmMoldSpecBt::getCastWidth).distinct().collect(Collectors.toList());
        List<String> rollLineNoList = list.stream().map(PmMoldSpecBt::getMscLineNo).distinct().collect(Collectors.toList());
        List<PmMoldSpecBt> existPmMoldSpecBtList = pmMoldSpecBtRepository.selectByCondition(Condition.builder(PmMoldSpecBt.class)
                .andWhere(Sqls.custom().andEqualTo(PmMoldSpecBt.FIELD_TENANT_ID, tenantId))
                .andWhere(Sqls.custom().andIn(PmMoldSpecBt.FIELD_CC_TYPE, ccTypeList))
                .andWhere(Sqls.custom().andIn(PmMoldSpecBt.FIELD_CAST_THICK, castThickList))
                .andWhere(Sqls.custom().andIn(PmMoldSpecBt.FIELD_CAST_WIDTH, castWidthList))
                .andWhere(Sqls.custom().andIn(PmMoldSpecBt.FIELD_MSC_LINE_NO, rollLineNoList))
                .build());

        // 与数据库数据之间是否重复
        if (CollectionUtils.isNotEmpty(existPmMoldSpecBtList)) {
            // 根据四个字段校验唯一性
            Map<String, PmMoldSpecBt> existPmMoldSpecBtMap = existPmMoldSpecBtList.stream().collect(Collectors.toMap(pmMoldSpecBt -> pmMoldSpecBt.getCcType() + "-"
                    + pmMoldSpecBt.getCastThick() + "-" + pmMoldSpecBt.getCastWidth() + "-"
                    + pmMoldSpecBt.getMscLineNo(), Function.identity(), (v1, v2) -> v1));
            for (int i = 0; i < list.size(); i++) {
                String key = list.get(i).getCcType() + "-" + list.get(i).getCastThick() + "-" + list.get(i).getCastWidth() + "-"
                        + list.get(i).getMscLineNo();
                if (existPmMoldSpecBtMap.containsKey(key)) {
                    addErrorMsg(i, MessageAccessor.getMessage("pm.mold_spec_bt_001",
                            new Object[]{list.get(i).getCcType(), list.get(i).getCastThick(), list.get(i).getCastWidth(),
                                    list.get(i).getMscLineNo()}).getDesc());
                    flag = false;
                }
            }
        }
        return flag;
    }
}
