package com.yeejoin.amos.api.openapi.face.service;


import cn.hutool.core.collection.ConcurrentHashSet;
import com.yeejoin.amos.api.openapi.enums.*;
import com.yeejoin.amos.api.openapi.face.model.*;
import com.yeejoin.amos.api.openapi.face.orm.dao.MidEquipRegistrationInfoMapper;
import com.yeejoin.amos.api.openapi.face.orm.entity.MidEquipRegistrationInfo;
import com.yeejoin.amos.boot.module.cylinder.api.dto.TzBaseEnterpriseInfoDto;
import net.sf.json.JSONArray;
import net.sf.json.JSONNull;
import net.sf.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.typroject.tyboot.core.restful.exception.instance.BadRequest;

import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;

/**
 * 气瓶数据校验
 */
@Component
public class CylinderFillingDataValidationService {

    @Autowired
    BaseEnterpriseInfoService enterpriseInfoService;

    @Autowired
    MidEquipRegistrationInfoMapper registrationInfoMapper;

    /**
     * 企业信息校验
     *
     * @param unitData
     */
    public void validateCylinderUnit(List<TmCylinderUnitModel> unitData) {
        JSONArray jsonArray = JSONArray.fromObject(unitData);
        // 1.必填校验
        List<String> errorRows = validateRequired(CylinderUnitFieldEnum.getAllRequireKeys(), jsonArray);
        if (!ObjectUtils.isEmpty(errorRows)) {
            throw new BadRequest(JSONArray.fromObject( errorRows.stream().map(e -> "必填字段不能为空：" + e).collect(Collectors.toList())).toString());
        }
        // 2.本次上传数据唯一性校验
        errorRows = validateUnique(CylinderUnitFieldEnum.getAllUniqueKeys(), jsonArray);
        if (!ObjectUtils.isEmpty(errorRows)) {
            throw new BadRequest(JSONArray.fromObject( errorRows.stream().map(e -> "上传数据重复：" + e).collect(Collectors.toList())).toString());
        }
//        // 3.检查企业统一社会信用代码是否存在
//        Set<String> creditCodes = getAllData(FillingBeforeFieldEnum.creditCode.name(), jsonArray);
//        errorRows = getNotExistEnterpriseInfoByCreditCode(creditCodes);
//        if (!ObjectUtils.isEmpty(errorRows)) {
//            throw new BadRequest(JSONArray.fromObject(errorRows.stream().map(e -> "企业统一社会信用代码不存在：" + e).collect(Collectors.toList())).toString());
//        }
    }


    /**
     * 校验气瓶基本信息数据
     *
     * @param infoData
     */
    public void validateCylinderInfo(List<TmCylinderInfoModel> infoData) {
        JSONArray jsonArray = JSONArray.fromObject(infoData);
        // 1.必填校验
        List<String> errorRows = validateRequired(CylinderInfoFieldEnum.getAllRequireKeys(), jsonArray);
        if (!ObjectUtils.isEmpty(errorRows)) {
            throw new BadRequest(JSONArray.fromObject( errorRows.stream().map(e -> "必填字段不能为空：" + e).collect(Collectors.toList())).toString());
        }
        // 2.本次上传数据唯一性校验
        errorRows = validateUnique(CylinderInfoFieldEnum.getAllUniqueKeys(), jsonArray);
        if (!ObjectUtils.isEmpty(errorRows)) {
            throw new BadRequest(JSONArray.fromObject(  errorRows.stream().map(e -> "上传数据重复：" + e).collect(Collectors.toList())).toString());
        }
//        // 3.检查气瓶唯一标识码是否存在
//        Set<String> sequenceCodes = getAllData(FillingBeforeFieldEnum.sequenceCode.name(), jsonArray);
//        errorRows = getNotExistSequenceCodes(sequenceCodes);
//        if (!ObjectUtils.isEmpty(errorRows)) {
//            throw new BadRequest(JSONArray.fromObject(  errorRows.stream().map(e -> "气瓶唯一标识码不存在：" + e).collect(Collectors.toList())).toString());
//        }
//        // 4.检查企业统一社会信用代码是否存在
//        Set<String> creditCodes = getAllData(FillingBeforeFieldEnum.creditCode.name(), jsonArray);
//        errorRows = getNotExistEnterpriseInfoByCreditCode(creditCodes);
//        if (!ObjectUtils.isEmpty(errorRows)) {
//            throw new BadRequest(JSONArray.fromObject(  errorRows.stream().map(e -> "企业统一社会信用代码不存在：" + e).collect(Collectors.toList())).toString());
//        }
    }

    /**
     * 校验气瓶标签
     *
     * @param tagData
     */
    public void validateCylinderTag(List<TmCylinderTagsModel> tagData) {
        JSONArray jsonArray = JSONArray.fromObject(tagData);
        // 1.必填校验
        List<String> errorRows = validateRequired(CylinderTagFieldEnum.getAllRequireKeys(), jsonArray);
        if (!ObjectUtils.isEmpty(errorRows)) {
            throw new BadRequest(JSONArray.fromObject( errorRows.stream().map(e -> "必填字段不能为空：" + e).collect(Collectors.toList())).toString());
        }

        // 2.本次上传数据唯一性校验
        errorRows = validateUnique(CylinderTagFieldEnum.getAllUniqueKeys(), jsonArray);
        if (!ObjectUtils.isEmpty(errorRows)) {
            throw new BadRequest(JSONArray.fromObject(  errorRows.stream().map(e -> "上传数据重复：" + e).collect(Collectors.toList())).toString());
        }
        // 3.检查气瓶唯一标识码是否存在
//        Set<String> sequenceCodes = getAllData(FillingBeforeFieldEnum.sequenceCode.name(), jsonArray);
//        errorRows = getNotExistSequenceCodes(sequenceCodes);
//        if (!ObjectUtils.isEmpty(errorRows)) {
//            throw new BadRequest(JSONArray.fromObject(  errorRows.stream().map(e -> "气瓶唯一标识码不存在：" + e).collect(Collectors.toList())).toString());
//        }
    }

    /**
     * 气瓶检验信息
     *
     * @param inspectionData
     */
    public void validateCylinderInspection(List<TmCylinderInspectionModel> inspectionData) {
        JSONArray jsonArray = JSONArray.fromObject(inspectionData);
        // 1.必填校验
        List<String> errorRows = validateRequired(CylinderInspectionFieldEnum.getAllRequireKeys(), jsonArray);
        if (!ObjectUtils.isEmpty(errorRows)) {
            throw new BadRequest(JSONArray.fromObject( errorRows.stream().map(e -> "必填字段不能为空：" + e).collect(Collectors.toList())).toString());
        }

        // 2.本次上传数据唯一性校验
        errorRows = validateUnique(CylinderInspectionFieldEnum.getAllUniqueKeys(), jsonArray);
        if (!ObjectUtils.isEmpty(errorRows)) {
            throw new BadRequest(JSONArray.fromObject(  errorRows.stream().map(e -> "上传数据重复：" + e).collect(Collectors.toList())).toString());
        }
        // 3.检查气瓶唯一标识码是否存在
//        Set<String> sequenceCodes = getAllData(FillingBeforeFieldEnum.sequenceCode.name(), jsonArray);
//        errorRows = getNotExistSequenceCodes(sequenceCodes);
//        if (!ObjectUtils.isEmpty(errorRows)) {
//            throw new BadRequest(JSONArray.fromObject(  errorRows.stream().map(e -> "气瓶唯一标识码不存在：" + e).collect(Collectors.toList())).toString());
//        }
    }


    /**
     * 校验审核信息
     *
     * @param inspectionData
     */
    public void validateCylinderFillingExamineModel(List<TmCylinderFillingExamineModel> inspectionData) {
        JSONArray jsonArray = JSONArray.fromObject(inspectionData);
        // 1.必填校验
        List<String> errorRows = validateRequired(CylinderFillingAuditFieldEnum.getAllRequireKeys(), jsonArray);
        if (!ObjectUtils.isEmpty(errorRows)) {
            throw new BadRequest(JSONArray.fromObject( errorRows.stream().map(e -> "必填字段不能为空：" + e).collect(Collectors.toList())).toString());
        }

        // 2.本次上传数据唯一性校验
        errorRows = validateUnique(CylinderFillingAuditFieldEnum.getAllUniqueKeys(), jsonArray);
        if (!ObjectUtils.isEmpty(errorRows)) {
            throw new BadRequest(JSONArray.fromObject(  errorRows.stream().map(e -> "上传数据重复：" + e).collect(Collectors.toList())).toString());
        }
        // 3.检查气瓶唯一标识码是否存在
//        Set<String> sequenceCodes = getAllData(FillingBeforeFieldEnum.sequenceCode.name(), jsonArray);
//        errorRows = getNotExistSequenceCodes(sequenceCodes);
//        if (!ObjectUtils.isEmpty(errorRows)) {
//            throw new BadRequest(JSONArray.fromObject(  errorRows.stream().map(e -> "气瓶唯一标识码不存在：" + e).collect(Collectors.toList())).toString());
//        }
    }

    /**
     * 验证气瓶充装数据
     * @return
     */
    public CylinderFillingDataValidationResultModel validateFilling(JSONObject jsonobject) throws ExecutionException, InterruptedException {
        CylinderFillingDataValidationResultModel result = new CylinderFillingDataValidationResultModel();
        if (ObjectUtils.isEmpty(jsonobject)) {
          throw new BadRequest("上传数据不能为空！！！");
        }
        if (!jsonobject.containsKey("fillingBefore") || ObjectUtils.isEmpty(jsonobject.get("fillingBefore"))) {
            throw new BadRequest("充装前检查数据不能为空！！！");
        }
        if (!jsonobject.containsKey("filling") || ObjectUtils.isEmpty(jsonobject.get("filling"))) {
            throw new BadRequest("充装数据不能为空！！！");
        }
        if (!jsonobject.containsKey("fillingAfter") || ObjectUtils.isEmpty(jsonobject.get("fillingAfter"))) {
            throw new BadRequest("充装后复查数据不能为空！！！");
        }

        Set<String> cylinderCodeSet = new ConcurrentHashSet<>();
        Set<String>  beforeErrorCylinderSet = new ConcurrentHashSet<>();
        Set<String>  recordErrorCylinderSet = new ConcurrentHashSet<>();
        Set<String>  afterErrorCylinderSet = new ConcurrentHashSet<>();

        CompletableFuture<List<String>> beforeFuture = CompletableFuture.supplyAsync(() -> {
            // 异步校验检验前数据
            JSONArray fillingBefore = jsonobject.getJSONArray("fillingBefore");
            if (!ObjectUtils.isEmpty(fillingBefore)) {
                for (int i = 0; i < fillingBefore.size(); i++) {
                    JSONObject row = fillingBefore.getJSONObject(i);
                    cylinderCodeSet.add(row.getString("sequenceCode"));
                }
            }
            return validateFillingBeforeData(fillingBefore, beforeErrorCylinderSet);
        });
        CompletableFuture<List<String>> recordFuture = CompletableFuture.supplyAsync(() -> {
            //  异步校验检填充数据
            JSONArray filling = jsonobject.getJSONArray("filling");
            if (!ObjectUtils.isEmpty(filling)) {
                for (int i = 0; i < filling.size(); i++) {
                    JSONObject row = filling.getJSONObject(i);
                    cylinderCodeSet.add(row.getString("sequenceCode"));
                }
            }
            return validateFillingRecordData(filling, recordErrorCylinderSet);
        });

        CompletableFuture<List<String>> afterFuture = CompletableFuture.supplyAsync(() -> {
            // 异步校验检填充后数据
            JSONArray fillingAfter = jsonobject.getJSONArray("fillingAfter");
            if (!ObjectUtils.isEmpty(fillingAfter)) {
                for (int i = 0; i < fillingAfter.size(); i++) {
                    JSONObject row = fillingAfter.getJSONObject(i);
                    cylinderCodeSet.add(row.getString("sequenceCode"));
                }
            }
            return validateFillinAfterData(jsonobject.getJSONArray("fillingAfter"), afterErrorCylinderSet);
        });

        /**
         * 等待校验结果
         */
        CompletableFuture.allOf(beforeFuture, recordFuture, afterFuture);
        result.setBeforeErrorData(beforeFuture.get());
        result.setRecordErrorData(recordFuture.get());
        result.setAfterErrorData(afterFuture.get());
        result.setCylinderNumber(cylinderCodeSet.size());

        result.setBeforeErrorCylinderNumber(beforeErrorCylinderSet.size());
        result.setRecordErrorCylinderNumber(recordErrorCylinderSet.size());
        result.setAfterErrorCylinderNumber(afterErrorCylinderSet.size());
        cylinderCodeSet.removeAll(beforeErrorCylinderSet);
        cylinderCodeSet.removeAll(recordErrorCylinderSet);
        cylinderCodeSet.removeAll(afterErrorCylinderSet);
        result.setSuccessCylinderNumber(cylinderCodeSet.size());
        return result;
    }


    /**
     * 验证检验前数据
     * @param jsonArray
     * @return List 异常数据
     */
    public List<String> validateFillingBeforeData(JSONArray jsonArray, Set<String>  errorCylinderSet) {
        // 1.必填校验
        List<String> errorRows = validateRequired(FillingBeforeFieldEnum.getAllRequireKeys(), jsonArray);
        if (!ObjectUtils.isEmpty(errorRows)) {
            errorRows.stream().forEach( json -> {
                String sequenceCode = JSONObject.fromObject(json).getString("sequenceCode");
                errorCylinderSet.add(sequenceCode);
            });
            return errorRows.stream().map(e -> "必填字段不能为空：" + e).collect(Collectors.toList());
        }
        // 2.本次上传数据唯一性校验
        errorRows = validateUnique(FillingBeforeFieldEnum.getAllUniqueKeys(), jsonArray);
        if (!ObjectUtils.isEmpty(errorRows)) {
            errorRows.stream().forEach( json -> {
                String sequenceCode = JSONObject.fromObject(json).getString("sequenceCode");
                errorCylinderSet.add(sequenceCode);
            });
            return errorRows.stream().map(e -> "上传数据重复：" + e).collect(Collectors.toList());
        }
//        // 3.检查气瓶唯一标识码是否存在
//        Set<String> sequenceCodes = getAllData(FillingBeforeFieldEnum.sequenceCode.name(), jsonArray);
//        errorRows = getNotExistSequenceCodes(sequenceCodes);
//        if (!ObjectUtils.isEmpty(errorRows)) {
//            return errorRows.stream().map(e -> "气瓶唯一标识码不存在：" + e).collect(Collectors.toList());
//        }
//        // 4.检查企业统一社会信用代码是否存在
//        Set<String> creditCodes = getAllData(FillingBeforeFieldEnum.creditCode.name(), jsonArray);
//        errorRows = getNotExistEnterpriseInfoByCreditCode(creditCodes);
//        if (!ObjectUtils.isEmpty(errorRows)) {
//            return errorRows.stream().map(e -> "企业统一社会信用代码不存在：" + e).collect(Collectors.toList());
//        }
        return null;
    }

    /**
     * 验证检验记录数据
     * @param jsonArray
     * @return List 异常数据
     */
    public List<String> validateFillingRecordData(JSONArray jsonArray, Set<String>  errorCylinderSet) {
        // 1.必填校验
        List<String> errorRows = validateRequired(FillingRecordFieldEnum.getAllRequireKeys(), jsonArray);
        if (!ObjectUtils.isEmpty(errorRows)) {
            errorRows.stream().forEach( json -> {
                String sequenceCode = JSONObject.fromObject(json).getString("sequenceCode");
                errorCylinderSet.add(sequenceCode);
            });
            return errorRows.stream().map(e -> "必填字段不能为空：：" + e).collect(Collectors.toList());
        }
        // 2.本次上传数据唯一性校验
        errorRows = validateUnique(FillingRecordFieldEnum.getAllUniqueKeys(), jsonArray);
        if (!ObjectUtils.isEmpty(errorRows)) {
            errorRows.stream().forEach( json -> {
                String sequenceCode = JSONObject.fromObject(json).getString("sequenceCode");
                errorCylinderSet.add(sequenceCode);
            });
            return errorRows.stream().map(e -> "上传数据重复：" + e).collect(Collectors.toList());
        }
//        // 3.检查气瓶唯一标识码是否存在
//        Set<String> sequenceCodes = getAllData(FillingBeforeFieldEnum.sequenceCode.name(), jsonArray);
//        errorRows = getNotExistSequenceCodes(sequenceCodes);
//        if (!ObjectUtils.isEmpty(errorRows)) {
//            return errorRows.stream().map(e -> "气瓶唯一标识码不存在：" + e).collect(Collectors.toList());
//        }
//        // 4.检查企业统一社会信用代码是否存在
//        Set<String> creditCodes = getAllData(FillingBeforeFieldEnum.creditCode.name(), jsonArray);
//        errorRows = getNotExistEnterpriseInfoByCreditCode(creditCodes);
//        if (!ObjectUtils.isEmpty(errorRows)) {
//            return errorRows.stream().map(e -> "企业统一社会信用代码不存在：" + e).collect(Collectors.toList());
//        }
        return null;
    }

    /**
     * 验证检验后数据
     * @param jsonArray
     * @return List 异常数据
     */
    public List<String> validateFillinAfterData(JSONArray jsonArray, Set<String>  errorCylinderSet) {

        // 1.必填校验
        List<String> errorRows = validateRequired(FillingAfterFieldEnum.getAllRequireKeys(), jsonArray);
        if (!ObjectUtils.isEmpty(errorRows)) {
            errorRows.stream().forEach( json -> {
                String sequenceCode = JSONObject.fromObject(json).getString("sequenceCode");
                errorCylinderSet.add(sequenceCode);
            });
            return errorRows.stream().map(e -> "必填字段不能为空：：" + e).collect(Collectors.toList());
        }
        // 2.本次上传数据唯一性校验
        errorRows = validateUnique(FillingAfterFieldEnum.getAllUniqueKeys(), jsonArray);
        if (!ObjectUtils.isEmpty(errorRows)) {
            errorRows.stream().forEach( json -> {
                String sequenceCode = JSONObject.fromObject(json).getString("sequenceCode");
                errorCylinderSet.add(sequenceCode);
            });
            return errorRows.stream().map(e -> "上传数据重复：" + e).collect(Collectors.toList());
        }
//        // 3.检查气瓶唯一标识码是否存在
//        Set<String> sequenceCodes = getAllData(FillingBeforeFieldEnum.sequenceCode.name(), jsonArray);
//        errorRows = getNotExistSequenceCodes(sequenceCodes);
//        if (!ObjectUtils.isEmpty(errorRows)) {
//            return errorRows.stream().map(e -> "气瓶唯一标识码不存在：" + e).collect(Collectors.toList());
//        }
//        // 4.检查企业统一社会信用代码是否存在
//        Set<String> creditCodes = getAllData(FillingBeforeFieldEnum.creditCode.name(), jsonArray);
//        errorRows = getNotExistEnterpriseInfoByCreditCode(creditCodes);
//        if (!ObjectUtils.isEmpty(errorRows)) {
//            return errorRows.stream().map(e -> "企业统一社会信用代码不存在：" + e).collect(Collectors.toList());
//        }
        return null;
    }

    /**
     * 必填校验
     * @param keys 需要校验的key
     * @param jsonArray 被校验数据
     * @return 校验结果 通过为 true，不通过为false
     */
    public List<String> validateRequired(List<String> keys, JSONArray jsonArray) {
        List<String> errorList = new ArrayList<>();
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject row = jsonArray.getJSONObject(i);
            for (String key : keys) {
                if (!row.containsKey(key) || ObjectUtils.isEmpty(row.get(key)) || row.get(key).equals(JSONNull.getInstance())) {
                    errorList.add(row.toString());
                }
            }
        }

        return errorList;
    }

    /**
     * 数据唯一性校验
     * @param keys 需要校验的key
     * @param jsonArray 被校验数据
     * @return 校验结果 通过为 true，不通过为false
     */
    public List<String> validateUnique(List<String> keys, JSONArray jsonArray) {
        Map<String, Set<Object>> valuesMap = new HashMap<>();
        List<String> errorList = new ArrayList<>();
        for (String key : keys) {
            valuesMap.put(key, new HashSet<>());
        }
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject row = jsonArray.getJSONObject(i);
            for (String key : keys) {
                if (valuesMap.get(key).contains(row.get(key))) {
                    errorList.add(row.toString());
                }
                valuesMap.get(key).add(row.get(key));
            }
        }

        return errorList;
    }

    /**
     * 获取指定 key的所有数据
     * @param key
     * @param jsonArray
     * @return
     */
    public Set<String> getAllData(String key, JSONArray jsonArray) {
        Set<String> sequenceCode = new HashSet<>();
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject row = jsonArray.getJSONObject(i);
            sequenceCode.add(row.get(key).toString());
        }
        return sequenceCode;
    }

    /**
     * 校验企业唯一信用代码
     * @param creditCodes
     * @return
     */
    public List<String> getNotExistEnterpriseInfoByCreditCode(Set<String> creditCodes) {
        List<TzBaseEnterpriseInfoDto> enterpriseInfos = enterpriseInfoService.getEnterpriseInfoByCreditCode(creditCodes);
        if (enterpriseInfos.size() < creditCodes.size()) {
            List<String> userCodes = enterpriseInfos.stream().map(TzBaseEnterpriseInfoDto::getUseCode).collect(Collectors.toList());
            return creditCodes.stream().filter(c -> !userCodes.contains(c)).collect(Collectors.toList());
        }
        return null;
    }

    /**
     *  获取不存在的气瓶编码
     * @param sequenceCodes
     * @return
     */
    public List<String> getNotExistSequenceCodes(Set<String> sequenceCodes) {
        List<MidEquipRegistrationInfo> useInfos = registrationInfoMapper.getUseInfoByEquipCode(sequenceCodes);
        if (useInfos.size() < sequenceCodes.size()) {
            List<String> equipCodes = useInfos.stream().map(e -> e.getEquCode()).collect(Collectors.toList());
            return sequenceCodes.stream().filter(c -> !equipCodes.contains(c)).collect(Collectors.toList());
        }
        return null;
    }

    /**
     * 气站卸液量记录数据校验
     *
     * @param offloadingData 卸液量数据
     */
    public void validateCylinderOffloadingData(List<TmCylinderOffloadingModel> offloadingData) {
        JSONArray jsonArray = JSONArray.fromObject(offloadingData);
        // 1.必填校验
        List<String> errorRows = validateRequired(CylinderOffloadingFieldEnum.getAllRequireKeys(), jsonArray);
        if (!ObjectUtils.isEmpty(errorRows)) {
            throw new BadRequest(JSONArray.fromObject( errorRows.stream().map(e -> "必填字段不能为空：" + e).collect(Collectors.toList())).toString());
        }
        // 2.本次上传数据唯一性校验
        errorRows = validateUnique(CylinderOffloadingFieldEnum.getAllUniqueKeys(), jsonArray);
        if (!ObjectUtils.isEmpty(errorRows)) {
            throw new BadRequest(JSONArray.fromObject( errorRows.stream().map(e -> "上传数据重复：" + e).collect(Collectors.toList())).toString());
        }
//        // 3.检查企业统一社会信用代码是否存在
//        Set<String> creditCodes = getAllData(FillingBeforeFieldEnum.creditCode.name(), jsonArray);
//        errorRows = getNotExistEnterpriseInfoByCreditCode(creditCodes);
//        if (!ObjectUtils.isEmpty(errorRows)) {
//            throw new BadRequest(JSONArray.fromObject(errorRows.stream().map(e -> "企业统一社会信用代码不存在：" + e).collect(Collectors.toList())).toString());
//        }
    }
}
