package com.jwipc.spe.logic.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.enums.SqlLike;
import com.baomidou.mybatisplus.core.toolkit.sql.SqlUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.googlecode.aviator.AviatorEvaluator;
import com.jwipc.aggregation.ModelAggregationService;
import com.jwipc.exception.DaoException;
import com.jwipc.page.PageUtil;
import com.jwipc.page.PageView;
import com.jwipc.query.BasePageQuery;
import com.jwipc.security.LoginUtil;
import com.jwipc.spe.constant.AppraisePlanStatus;
import com.jwipc.spe.constant.EvaluationCycleType;
import com.jwipc.spe.constant.QuotaType;
import com.jwipc.spe.constant.SequenceConst;
import com.jwipc.spe.convert.SupAppraisePlanConvert;
import com.jwipc.spe.convert.SupAppraisePlanSupplierConvert;
import com.jwipc.spe.dto.*;
import com.jwipc.spe.entity.*;
import com.jwipc.spe.logic.RectifiedNoticeLogic;
import com.jwipc.spe.logic.SupAppraisePlanLogic;
import com.jwipc.spe.model.dto.ScoreReportDTO;
import com.jwipc.spe.model.po.AppraiseSupplierInfoPO;
import com.jwipc.spe.model.po.PlanSupplierCalPO;
import com.jwipc.spe.model.po.RectifiedSupplierPO;
import com.jwipc.spe.model.po.SupAppraiseResultDetailPO;
import com.jwipc.spe.model.query.AppraiseSupplierQuery;
import com.jwipc.spe.model.query.ScoreReportQuery;
import com.jwipc.spe.model.query.SupAppraisePlanQuery;
import com.jwipc.spe.service.*;
import com.jwipc.supplier.clent.dto.SupplierDTO;
import com.jwipc.supplier.client.SupplierClient;
import com.jwipc.sys.client.FileClient;
import com.jwipc.sys.client.SequenceClient;
import com.jwipc.sys.client.SupplierEmailClient;
import com.jwipc.sys.client.dto.FileResposeCDTO;
import com.jwipc.sys.client.dto.SupplierEmailCDTO;
import com.jwipc.util.DateUtils;
import com.jwipc.util.EasyExcelImportUtils;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;


/**
 * <p> </p>
 *
 * @author BOGON
 * @version 1.0
 * @since JDK 1.8
 */
@Service
@RequiredArgsConstructor
public class SupAppraisePlanLogicImpl implements SupAppraisePlanLogic {
    private final ISupAppraisePlanService supAppraisePlanService;
    private final SupAppraisePlanConvert supAppraisePlanConvert;
    private final ModelAggregationService modelAggregationService;
    private final ISupAppraiseResultDetailService supAppraiseResultDetailService;
    private final ISupAppraisePlanSupplierService supAppraisePlanSupplierService;
    private final SupAppraisePlanSupplierConvert supAppraisePlanSupplierConvert;
    private final ISupAppraiseTemplateService supAppraiseTemplateService;
    private final ISupTemDimensionService temDimensionService;
    private final ISupTemQuotaService supTemQuotaService;
    private final FileClient fileClient;
    private final SupplierClient supplierClient;
    private final SupplierEmailClient supplierEmailClient;
    private final SequenceClient sequenceClient;
    private final RectifiedNoticeLogic rectifiedNoticeLogic;

    @Override
    public PageView list(SupAppraisePlanQuery query) {
        Page<SupAppraisePlan> page = PageUtil.toPage(query);
        final LambdaQueryWrapper<SupAppraisePlan> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(StrUtil.isNotEmpty(query.getCode()), SupAppraisePlan::getPlanCode,
                SqlUtils.concatLike(query.getCode(), SqlLike.DEFAULT));
        queryWrapper.like(StrUtil.isNotEmpty(query.getTitle()), SupAppraisePlan::getPlanTitle,
                SqlUtils.concatLike(query.getTitle(), SqlLike.DEFAULT));
        queryWrapper.in(StrUtil.isNotEmpty(query.getStatus()), SupAppraisePlan::getStatus, query.getStatusList());
        queryWrapper.eq(Objects.nonNull(query.getEvaluationCycle()), SupAppraisePlan::getEvaluationCycle,
                query.getEvaluationCycle());
        queryWrapper.orderByDesc(SupAppraisePlan::getCreateTime);
        final List<SupAppraisePlan> list = supAppraisePlanService.list(page, queryWrapper);
        final List<SupAppraisePlanBaseDTO> planBaseDTOS = supAppraisePlanConvert.entities2Dtos(list);
        modelAggregationService.processRelationAggregation(planBaseDTOS);
        return PageUtil.getPV(planBaseDTOS, page.getTotal());
    }

    @Override
    public PageView scoreReportList(ScoreReportQuery query) {
        Page<ScoreReportDTO> page = PageUtil.toPage(query);
        List<ScoreReportDTO> list = supAppraisePlanService.findPageByQuery(page, query);

        return PageUtil.getPV(list, page.getTotal());
    }

    @Override
    public SupAppraisePlanDetailDTO getDetail(Long id) {
        SupAppraisePlanDetailDTO data;
        final SupAppraisePlan appraisePlan = supAppraisePlanService.getById(id);
        final Integer year = appraisePlan.getYear();
        final Integer quarter = appraisePlan.getQuarter();
        final Integer month = appraisePlan.getMonth();
        String date = StrUtil.EMPTY;
        if (appraisePlan.getEvaluationCycle() == EvaluationCycleType.YEAR.getValue()) {
            date = year + "-01";
        } else if (appraisePlan.getEvaluationCycle() == EvaluationCycleType.QUARTER.getValue()) {
            date = year + "-" + (quarter * 3);
        } else if (appraisePlan.getEvaluationCycle() == EvaluationCycleType.MONTH.getValue()) {
            date = year + "-" + month;
        }

        if (Objects.nonNull(appraisePlan)) {
            data = supAppraisePlanConvert.entity2Dto(appraisePlan);
        } else {
            data = new SupAppraisePlanDetailDTO();
            data.setId(0L);
        }
        modelAggregationService.processRelationAggregation(data);
        data.setEvaluationDate(date);
        return data;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveOrUpdate(SupAppraisePlanSaveDTO supAppraisePlanSaveDTO) {
        final String evaluationDate = supAppraisePlanSaveDTO.getEvaluationDate();
        final DateTime parse = DateUtil.parse(evaluationDate, DateUtils.yyyyMMDash);
        final EvaluationCycleType cycleType = EvaluationCycleType.forValue(supAppraisePlanSaveDTO.getEvaluationCycle());
        switch (cycleType) {
            case YEAR:
                supAppraisePlanSaveDTO.setYear(parse.year());
                supAppraisePlanSaveDTO.setQuarter(0);
                supAppraisePlanSaveDTO.setMonth(0);
                break;
            case QUARTER:
                supAppraisePlanSaveDTO.setYear(parse.year());
                supAppraisePlanSaveDTO.setQuarter(parse.quarter());
                supAppraisePlanSaveDTO.setMonth(0);
                break;
            case MONTH:
                supAppraisePlanSaveDTO.setYear(parse.year());
                supAppraisePlanSaveDTO.setQuarter(0);
                supAppraisePlanSaveDTO.setMonth(parse.month() + 1);
                break;

        }
        if (supAppraisePlanSaveDTO.getId().compareTo(0L) == 0) {
            supAppraisePlanSaveDTO.setCreateUserId(LoginUtil.getUserId());
            supAppraisePlanSaveDTO.setCreateUserName(LoginUtil.getName());
            supAppraisePlanSaveDTO.setCreateTime(LocalDateTime.now());
            supAppraisePlanSaveDTO.setId(null);
        } else {
            supAppraisePlanSaveDTO.setUpdateTime(LocalDateTime.now());
            supAppraisePlanSaveDTO.setUpdateUserId(LoginUtil.getUserId());
            supAppraisePlanSaveDTO.setUpdateUserName(LoginUtil.getName());
            //需要删除关联数据
            supAppraiseResultDetailService.remove(
                    new LambdaQueryWrapper<SupAppraiseResultDetail>().eq(SupAppraiseResultDetail::getPlanId,
                            supAppraisePlanSaveDTO.getId()));
            supAppraisePlanSupplierService.remove(
                    new LambdaQueryWrapper<SupAppraisePlanSupplier>().eq(SupAppraisePlanSupplier::getPlanId,
                            supAppraisePlanSaveDTO.getId()));
        }
        SupAppraisePlan ap = supAppraisePlanConvert.dto2Entity(supAppraisePlanSaveDTO);
        final SupAppraiseTemplate template = supAppraiseTemplateService.getById(ap.getTemplateId());
        if (Objects.isNull(template)) {
            throw new DaoException("模板不存在!");
        }
        ap.setPlanCode(sequenceClient.createSequenceNo(SequenceConst.APPRAISE_PLAN_CODE.getCode()));
        ap.setTemplateId(template.getId());
        ap.setTemplateName(template.getTemplateName());
        supAppraisePlanService.saveOrUpdate(ap);
        //保存明细
        saveDetail(ap, template);
    }

    @Override
    public PageView detailList(AppraiseSupplierQuery query) {
        final List<Map<String, Object>> result = getPlanDetail(query);
        this.hanlderStr2Num(result);
        return PageUtil.getPV(result, result.size());
    }

    @Override
    public void hanlderStr2Num(List<Map<String, Object>> planDetails) {
        // 处理数据
        for (Map<String, Object> map : planDetails) {
            for (Map.Entry<String, Object> entry : map.entrySet()) {
                Object value = entry.getValue();
                if (entry.getKey().equals("ZW_PZ_30") || entry.getKey().equals("ZW_PZ_31")) {
                    if (value instanceof String) {
                        final String string = value.toString();
                        if (string.equals("0.0")) {
                            map.put(entry.getKey(), StrUtil.EMPTY);
                            continue;
                        }
                    }
                }
                if (value instanceof Number) {
                    String formattedValue = new java.text.DecimalFormat("#.##").format((Number) value);
                    map.put(entry.getKey(), new BigDecimal(formattedValue));
                } else if (value instanceof String) {
                    try {
                        Double numericValue = Double.parseDouble((String) value);
                        String formattedValue = new java.text.DecimalFormat("#.##").format(numericValue);
                        map.put(entry.getKey(), new BigDecimal(formattedValue));
                    } catch (NumberFormatException e) {
                        // 不是数字的字符串，保持原样
                    }
                }
            }
        }
    }

    @Override
    public List<Map<String, Object>> getPlanDetail(AppraiseSupplierQuery query) {
        //需要组装数据，把同一个供应商的数据组装成map
        // 根据 supplierPlanId 进行分组
        final List<SupAppraisePlanSupplier> list = supAppraisePlanSupplierService.findForQuery(query);
        final Set<Long> planSupplierIds = list.stream().map(SupAppraisePlanSupplier::getId).collect(Collectors.toSet());
        if (CollUtil.isEmpty(planSupplierIds)) {
            return Lists.newArrayList();
        }
        final LambdaQueryWrapper<SupAppraiseResultDetail> queryWrapper =
                new LambdaQueryWrapper<SupAppraiseResultDetail>().eq(
                                SupAppraiseResultDetail::getPlanId, query.getPlanId())
                        .in(SupAppraiseResultDetail::getSupplierPlanId, planSupplierIds);

        final List<SupAppraiseResultDetail> resultDetails = supAppraiseResultDetailService.list(queryWrapper);
        // 根据 supplierPlanId 进行分组
        Map<Long, List<SupAppraiseResultDetail>> groupedBySupplierPlanId = resultDetails.stream()
                .collect(Collectors.groupingBy(SupAppraiseResultDetail::getSupplierPlanId));
        List<SupAppraisePlanSupplierBaseDTO> list1 = supAppraisePlanSupplierConvert.entities2Dtos(list);
        modelAggregationService.processRelationAggregation(list1);
        final Map<Long, SupAppraisePlanSupplierBaseDTO> supplierCache = list1.stream()
                .collect(Collectors.toMap(SupAppraisePlanSupplierBaseDTO::getId, dto -> dto));
        final Set<String> supplierCodeCache = list1.stream().map(SupAppraisePlanSupplierBaseDTO::getSupplierCode)
                .collect(Collectors.toSet());
        List<Map<String, Object>> result = Lists.newArrayList();
        final SupAppraisePlan ap = supAppraisePlanService.getById(query.getPlanId());
        String date = StrUtil.EMPTY;
        if (ap.getEvaluationCycle().compareTo(EvaluationCycleType.YEAR.getValue()) == 0) {
            date = ap.getYear() + "年";
        } else if (ap.getEvaluationCycle().compareTo(EvaluationCycleType.MONTH.getValue()) == 0) {
            date = ap.getYear() + "年" + ap.getMonth() + "月";

        } else if (ap.getEvaluationCycle().compareTo(EvaluationCycleType.QUARTER.getValue()) == 0) {
            date = ap.getYear() + "年" + ap.getQuarter() + "季度";
        }
        final List<SupplierEmailCDTO> supplierEmails = supplierEmailClient.getSupplierEmails(supplierCodeCache);
        final Map<String, List<SupplierEmailCDTO>> supplierPurchaseUserCache = supplierEmails.stream()
                .collect(Collectors.groupingBy(SupplierEmailCDTO::getSupplierCode));
        for (Long l : groupedBySupplierPlanId.keySet()) {
            Map<String, Object> tmp = Maps.newHashMap();
            final SupAppraisePlanSupplierBaseDTO supAppraisePlanSupplierBaseDTO = supplierCache.get(l);
            final String supplierCode = supAppraisePlanSupplierBaseDTO.getSupplierCode();
            tmp.put("supplierCode", supplierCode);
            tmp.put("supplierName", supAppraisePlanSupplierBaseDTO.getSupplierName());
            final List<SupplierEmailCDTO> value = supplierPurchaseUserCache.get(supplierCode);
            if (CollUtil.isNotEmpty(value)) {
                final Set<String> strings = value.stream().filter(a -> StrUtil.isNotEmpty(a.getPuserName()))
                        .map(SupplierEmailCDTO::getPuserName).collect(Collectors.toSet());
                tmp.put("purchaseUser", StrUtil.join(",", strings));

                final Set<String> purchaseCategoryNames = value.stream()
                        .filter(a -> StrUtil.isNotEmpty(a.getPurchaseCategoryName()))
                        .map(SupplierEmailCDTO::getPurchaseCategoryName).collect(Collectors.toSet());
                tmp.put("purchaseCategoryNames", StrUtil.join(",", purchaseCategoryNames));

                final Set<String> sqes = value.stream()
                        .filter(a -> StrUtil.isNotEmpty(a.getSqeName()))
                        .map(SupplierEmailCDTO::getSqeName).collect(Collectors.toSet());
                tmp.put("sqe", StrUtil.join(",", sqes));

                final Set<String> ces = value.stream()
                        .filter(a -> StrUtil.isNotEmpty(a.getCeName()))
                        .map(SupplierEmailCDTO::getCeName).collect(Collectors.toSet());
                tmp.put("ce", StrUtil.join(",", ces));
            } else {
                tmp.put("purchaseUser", "");
                tmp.put("purchaseCategoryNames", "");
                tmp.put("sqe", "");
                tmp.put("ce", "");
            }
            tmp.put("date", date);
            tmp.put("status", supAppraisePlanSupplierBaseDTO.getStatus());
            tmp.put("id", supAppraisePlanSupplierBaseDTO.getId());
            final List<SupAppraiseResultDetail> supAppraiseResultDetails = groupedBySupplierPlanId.get(l);
            for (SupAppraiseResultDetail supAppraiseResultDetail : supAppraiseResultDetails) {
                tmp.put(supAppraiseResultDetail.getQuotaCode(), supAppraiseResultDetail.getFinalScore());
            }
            result.add(tmp);
        }
        this.hanlderStr2Num(result);
        return result;
    }

    @Override
    public void updateStatus(Long planId) {
        supAppraisePlanService.update(new LambdaUpdateWrapper<SupAppraisePlan>().eq(SupAppraisePlan::getId, planId)
                .set(SupAppraisePlan::getStatus, AppraisePlanStatus.SCORE_ING.getIndex()));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void submitScore(Integer type, SubmitScoreDTO submitScoreDTO) {
        final Long planId = submitScoreDTO.getPlanId();
        commManualScoring(planId, submitScoreDTO.getItem(), type);
        if (type == 2) {
            //需要更新考核计划的状态,变成评分结束
            supAppraisePlanService.update(new LambdaUpdateWrapper<SupAppraisePlan>().eq(SupAppraisePlan::getId, planId)
                    .set(SupAppraisePlan::getStatus, AppraisePlanStatus.SCORED.getIndex()));
            //需要修改供应商警告状态
            needWard(planId);
            //需要自动发布整改通知单
            //
            //查询C和D
            final List<SupAppraiseResultDetail> list = supAppraiseResultDetailService.list(
                    new LambdaQueryWrapper<SupAppraiseResultDetail>().eq(SupAppraiseResultDetail::getPlanId, planId)
                            .in(SupAppraiseResultDetail::getFinalScore, Lists.newArrayList("C", "D"))
                            .eq(SupAppraiseResultDetail::getQuotaCode, "ZW_PZ_26"));
            if (CollUtil.isNotEmpty(list)) {
                final String ids = list.stream().map(detail -> String.valueOf(detail.getSupplierPlanId()))
                        .collect(Collectors.joining(","));
                rectifiedNoticeLogic.saveBatchNotice(ids, planId);
            }
        }
    }

    @Override
    public void needWard(Long planId) {
        List<ScoreReportQuery> queries = new ArrayList<>();
        LocalDate now = LocalDate.now();
        ScoreReportQuery query1 = new ScoreReportQuery();
        query1.setYear(String.valueOf(now.plusMonths(-1).getYear()));
        query1.setMonth(String.valueOf(now.plusMonths(-1).getMonth().getValue()));
        queries.add(query1);

        ScoreReportQuery query2 = new ScoreReportQuery();
        query2.setYear(String.valueOf(now.plusMonths(-2).getYear()));
        query2.setMonth(String.valueOf(now.plusMonths(-2).getMonth().getValue()));
        queries.add(query2);

        ScoreReportQuery query0 = new ScoreReportQuery();
        query0.setYear(String.valueOf(now.getYear()));
        query0.setMonth(String.valueOf(now.getMonth().getValue()));
        queries.add(query0);

        List<ScoreReportDTO> list = supAppraisePlanService.selectNeedWarnList(queries);
        if (CollectionUtils.isNotEmpty(list)) {
            List<Long> supplierIds = list.stream().filter(item -> item.getCdLevelCount().compareTo(3) >= 0)
                    .map(ScoreReportDTO::getSupplierId).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(supplierIds)) {
                LambdaQueryWrapper<SupAppraisePlanSupplier> planSupplierLambdaQueryWrapper = new LambdaQueryWrapper<>();
                planSupplierLambdaQueryWrapper.in(SupAppraisePlanSupplier::getSupplierId, supplierIds);
                planSupplierLambdaQueryWrapper.ne(SupAppraisePlanSupplier::getCdFlag, 1);
                planSupplierLambdaQueryWrapper.eq(SupAppraisePlanSupplier::getPlanId, planId);
                List<SupAppraisePlanSupplier> supAppraisePlanSuppliers = supAppraisePlanSupplierService.list(
                        planSupplierLambdaQueryWrapper);
                if (CollectionUtils.isNotEmpty(supAppraisePlanSuppliers)) {
                    supAppraisePlanSuppliers.forEach(item -> {
                        item.setCdFlag(1);
                    });
                    supAppraisePlanSupplierService.updateBatchById(supAppraisePlanSuppliers);
                }
            }
        }

    }

    @Override
    public void remove(Long id) {
        supAppraisePlanService.removeById(id);
        supAppraisePlanSupplierService.remove(
                new LambdaQueryWrapper<SupAppraisePlanSupplier>().eq(SupAppraisePlanSupplier::getPlanId, id));
        supAppraiseResultDetailService.remove(
                new LambdaQueryWrapper<SupAppraiseResultDetail>().eq(SupAppraiseResultDetail::getPlanId, id));
    }

    @Override
    public List<SupAppraisePlan> selectPlanYearList() {
        List<SupAppraisePlan> list = supAppraisePlanService.selectPlanYearList();
        return list;
    }

    @Override
    public List<ScoreReportDTO> listAll(ScoreReportQuery scoreReportQuery) {
        List<ScoreReportDTO> list = supAppraisePlanService.findPageByQuery(null, scoreReportQuery);
        return list;
    }


    @Override
    public PageView rectifiedSupplierList(Long planId) {
        //查询当前计划下的需要整改供应商
        List<RectifiedSupplierPO> list = supAppraisePlanSupplierService.findRectifiedSupplier(planId);
        List<RectifiedSupplierDTO> result = supAppraisePlanSupplierConvert.convert1(list);
        return PageUtil.getPV(result);
    }

    @Override
    public PageView getSupplierAppraisePlan(BasePageQuery basePageQuery, Long supplierId) {
        final Page<Object> page = PageUtil.toPage(basePageQuery);
        List<AppraiseSupplierInfoPO> result = supAppraisePlanSupplierService.getSupplierAppraisePlan(page, supplierId,
                AppraisePlanStatus.SCORED.getIndex());
        List<AppraiseSupplierInfoDTO> supplierInfoDTOS = supAppraisePlanSupplierConvert.po2toDtos(result);
        modelAggregationService.processRelationAggregation(supplierInfoDTOS);
        return PageUtil.getPV(supplierInfoDTOS, page.getTotal());
    }

    private void commManualScoring(Long planId, List<JSONObject> jsonArray, int type) {
        List<SupAppraiseResultDetail> updateLists = Lists.newArrayList();
        Set<String> key = Sets.newHashSet();
        //需要先找到供应商编码
        final Set<String> supplierCodes = jsonArray.stream().map(a -> a.getString("supplierCode"))
                .collect(Collectors.toSet());
        final List<SupplierDTO> supplierByCodes = supplierClient.getSupplierByCodes(supplierCodes);
        final Map<String, Long> supplierCache = supplierByCodes.stream()
                .collect(Collectors.toMap(SupplierDTO::getSupplierCode, SupplierDTO::getId));
        List<SupAppraiseResultDetailPO> list = supAppraiseResultDetailService.findBySupplierId(planId);
        //供应商id分组
        final Map<String, SupAppraiseResultDetailPO> cache = list.stream()
                .collect(Collectors.toMap(a -> a.getSupplierId() + "&&" + a.getQuotaCode(), b -> b));
        //组装成供应商ID+指标编号的key

        for (JSONObject o : jsonArray) {
            JSONObject item = o;
            String supplierCode = item.getString("supplierCode");
            key.add(supplierCode);
            for (String s : item.keySet()) {
                if (s.equals("supplierCode")) {
                    continue;
                }
                final String val = getStrVal(item.get(s));
                if (Strings.isNullOrEmpty(val)) {
                    continue;
                }
                final SupAppraiseResultDetailPO supAppraiseResultDetailPO = cache.get(
                        supplierCache.get(supplierCode) + "&&" + s);
                SupAppraiseResultDetail appraiseResultDetail = supAppraisePlanConvert.po2Entity1(
                        supAppraiseResultDetailPO);
                if (Objects.isNull(appraiseResultDetail)) {
                    continue;
                }
                if (NumberUtil.isNumber(val)) {
                    Double score = Double.valueOf(val);
                    final Double maxScore = appraiseResultDetail.getMaxScore();
                    //增加最高分限制
                    if (!Objects.isNull(maxScore)) {
                        if (score.compareTo(maxScore) >= 0) {
                            score = maxScore;
                        }
                    }
                    appraiseResultDetail.setEvaluationScore(String.valueOf(score));
                } else {
                    appraiseResultDetail.setEvaluationScore(val);
                }

                appraiseResultDetail.setFinalScore(appraiseResultDetail.getEvaluationScore());
                updateLists.add(appraiseResultDetail);
            }
        }
        if (CollectionUtil.isNotEmpty(updateLists)) {
            supAppraiseResultDetailService.updateBatchById(updateLists);
        }
        if (type == 0) {
        } else if (type == 1 || type == 2) {

            Set<Long> calTotalSupplierPlan = Sets.newHashSet();
            for (String supplierCode : key) {
                final PlanSupplierCalPO calculate = supAppraisePlanSupplierService.findForCalculate(planId,
                        supplierCache.get(supplierCode));
                this.calSysGet(calculate);
                calTotalSupplierPlan.add(calculate.getPlanSupplierId());

            }
            this.calTotal(calTotalSupplierPlan);
        }

    }

    @Transactional(rollbackFor = Exception.class)
    public void calTotal(Set<Long> calTotalSupplierPlan) {
        if (CollectionUtil.isNotEmpty(calTotalSupplierPlan)) {
            List<SupAppraiseResultDetail> updateLists = Lists.newArrayList();
            List<SupAppraiseResultDetail> appraiseResultDetails = supAppraiseResultDetailService.list(
                    new LambdaQueryWrapper<SupAppraiseResultDetail>().in(SupAppraiseResultDetail::getSupplierPlanId,
                            calTotalSupplierPlan));
            final Map<Long, List<SupAppraiseResultDetail>> idMaps = appraiseResultDetails.stream()
                    .collect(Collectors.groupingBy(SupAppraiseResultDetail::getSupplierPlanId));

            for (Long aLong : idMaps.keySet()) {
                final List<SupAppraiseResultDetail> appraiseResultDetails1 = idMaps.get(aLong);
                SupAppraiseResultDetail total = null;
                SupAppraiseResultDetail level = null;
                final Map<String, Object> evnMap = Maps.newHashMap();
                for (SupAppraiseResultDetail appraiseResultDetail : appraiseResultDetails1) {
                    evnMap.put("Total" + appraiseResultDetail.getDimensionCode(),
                            appraiseResultDetail.getDimensionTotal());
                    evnMap.put("Weight" + appraiseResultDetail.getDimensionCode(),
                            appraiseResultDetail.getDimensionWeight());

                    if (appraiseResultDetail.getQuotaCode().equals("ZW_PZ_25")) {
                        total = appraiseResultDetail;
                    } else if (appraiseResultDetail.getQuotaCode().equals("ZW_PZ_26")) {
                        level = appraiseResultDetail;
                    } else {
                        this.setEvnParams(evnMap, appraiseResultDetail);
                    }
                }
                if (!Objects.isNull(total)) {
                    final String calculationFormula = total.getCalculationFormula();
                    final Object execute = AviatorEvaluator.execute(calculationFormula, evnMap);
                    final String strVal = getStrVal(execute);
                    total.setFinalScore(strVal);
                    SupAppraiseResultDetail tt = new SupAppraiseResultDetail();
                    tt.setId(total.getId());
                    tt.setFinalScore(total.getFinalScore());
                    this.setEvnParams(evnMap, total);
                    updateLists.add(tt);
                }

                if (!Objects.isNull(level)) {
                    final String calculationFormula = level.getCalculationFormula();
                    final Object execute = AviatorEvaluator.execute(calculationFormula, evnMap);
                    final String strVal = getStrVal(execute);
                    level.setFinalScore(strVal);
                    SupAppraiseResultDetail tt = new SupAppraiseResultDetail();
                    tt.setId(level.getId());
                    tt.setFinalScore(level.getFinalScore());
                    updateLists.add(tt);
                }
            }

            if (CollectionUtil.isNotEmpty(updateLists)) {
                supAppraiseResultDetailService.updateBatchById(updateLists);
            }
        }
    }

    public void saveDetail(SupAppraisePlan ap, SupAppraiseTemplate template) {
        final FileResposeCDTO fileForDownload = fileClient.getFileForDownload(ap.getImportFile());
        try {
            List<Map<String, String>> dataList = EasyExcelImportUtils.parseExcelToData(
                    new FileInputStream(fileForDownload.getFilePath()), 3);
            // 使用 Stream API 从 dataList 中提取 supplierCode 的值并放入 Set 中
            Set<String> supplierCodeSet = dataList.stream().map(data -> data.get("supplierCode"))
                    .filter(Objects::nonNull) // 过滤掉为null的值
                    .collect(Collectors.toSet());
            final List<SupplierDTO> supplierByCodes = supplierClient.getSupplierByCodes(supplierCodeSet);
            Map<String, SupplierDTO> supplierMap = supplierByCodes.stream()
                    .collect(Collectors.toMap(SupplierDTO::getSupplierCode, dto -> dto));
            /**
             * 校验Excel是否填写正确
             */
            List<String> tipMsg = Lists.newArrayList();
            int i = 4;
            for (Map<String, String> stringObjectMap : dataList) {
                final String supplierCode = stringObjectMap.get("supplierCode");
                if (Strings.isNullOrEmpty(supplierCode)) {
                    tipMsg.add("第" + i + "行供应商编码不能为空");
                    i = i + 1;
                    continue;
                }

                if (!supplierMap.keySet().contains(supplierCode)) {
                    tipMsg.add("第" + i + "行供应商不存在");
                    i = i + 1;
                    continue;
                }
                final SupplierDTO supplierDTO = supplierMap.get(supplierCode);
                Integer count = supAppraisePlanSupplierService.findExtisFlag(ap.getYear(), ap.getQuarter(),
                        ap.getMonth(), supplierDTO.getId(), ap.getCompanyCode(), ap.getId());
                if (count > 0) {
                    tipMsg.add("第" + i + "行已经有对应考核");
                    i = i + 1;
                    continue;
                }
                i = i + 1;
            }
            if (CollectionUtil.isNotEmpty(tipMsg)) {
                throw new DaoException(StrUtil.join("<br/>", tipMsg));
            }
            /**
             * 存储数据
             * 1.存储供应商、物料组和计划的关系
             * 2.存储各个指标的数据
             */
            /**
             * Excel模板中存储各个指标数据，如果没有值就存0;
             */
            List<SupAppraiseResultDetail> inserLists = Lists.newArrayList();
            List<Long> supplierPlanIds = Lists.newArrayList();
            Map<String, SupAppraiseResultDetail> supplierDetail = Maps.newHashMap();
            List<SupTemDimension> dimensions = temDimensionService.list(
                    new LambdaQueryWrapper<SupTemDimension>().eq(SupTemDimension::getTemplateId, template.getId()));
            final Map<String, SupTemDimension> dimensionMap = dimensions.stream()
                    .collect(Collectors.toMap(SupTemDimension::getDimensionCode, a -> a));
            for (Map<String, String> stringObjectMap : dataList) {
                //处理供应商计划明细
                final String supplierCode = stringObjectMap.get("supplierCode");
                final SupplierDTO supplierDTO = supplierMap.get(supplierCode);
                SupAppraisePlanSupplier appraisePlanSupplier = new SupAppraisePlanSupplier();
                appraisePlanSupplier.setPlanId(ap.getId());
                appraisePlanSupplier.setCompanyCode(ap.getCompanyCode());
                appraisePlanSupplier.setSupplierId(supplierDTO.getId());
                supAppraisePlanSupplierService.save(appraisePlanSupplier);
                final Long supplierPlanId = appraisePlanSupplier.getId();
                /**
                 * 处理指标项
                 */
                for (String s : stringObjectMap.keySet()) {
                    if (Strings.isNullOrEmpty(s)) {
                        continue;
                    }
                    SupTemQuota quota = supTemQuotaService.getOne(
                            new LambdaQueryWrapper<SupTemQuota>().eq(SupTemQuota::getTemplateId, template.getId())
                                    .eq(SupTemQuota::getQuotaCode, s), false);
                    if (Objects.isNull(quota)) {
                        continue;
                    }
                    String strVal = stringObjectMap.get(s);
                    if (Strings.isNullOrEmpty(strVal)) {
                        strVal = "0";
                    }
                    final String dimensionCode = quota.getDimensionCode();
                    SupAppraiseResultDetail appraiseResultDetail = new SupAppraiseResultDetail();
                    final SupTemDimension dimension = dimensionMap.get(dimensionCode);
                    if (!Objects.isNull(dimension)) {
                        final Integer totalScore = dimension.getTotalScore();
                        final Integer dimensionWeight = dimension.getDimensionWeight();
                        appraiseResultDetail.setDimensionTotal(totalScore);
                        appraiseResultDetail.setDimensionWeight(dimensionWeight);
                    }
                    appraiseResultDetail.setQuotaCode(quota.getQuotaCode());
                    appraiseResultDetail.setEvelSort(quota.getEvelSort());
                    appraiseResultDetail.setEditFlag(quota.getEditFlag());
                    appraiseResultDetail.setDimensionCode(dimensionCode);
                    appraiseResultDetail.setPlanId(ap.getId());
                    appraiseResultDetail.setSupplierPlanId(supplierPlanId);
                    appraiseResultDetail.setQuotaType(quota.getQuotaType());
                    appraiseResultDetail.setQuotaDesc(quota.getQuotaDesc());
                    appraiseResultDetail.setCalculationFormula(quota.getCalculationFormula());
                    appraiseResultDetail.setReportFlag(quota.getReportFlag());
                    appraiseResultDetail.setSupplierFlag(quota.getSupplierFlag());
                    appraiseResultDetail.setDimensionName(quota.getDimensionName());
                    appraiseResultDetail.setMaxScore(quota.getMaxScore());
                    if (quota.getQuotaType().equals(QuotaType.IMPORT.getValue())) {
                        appraiseResultDetail.setEvaluationScore(strVal);
                        appraiseResultDetail.setFinalScore(strVal);
                        //需要把
                        if (appraiseResultDetail.getQuotaCode().equals("ZW_PZ_13")) {
                            appraiseResultDetail.setQuotaType(QuotaType.MANUAL_QUOTA.getValue());
                        }
                    } else if (appraiseResultDetail.getQuotaCode().equals("ZW_PZ_24") ) {
                        appraiseResultDetail.setEvaluationScore("60");
                        appraiseResultDetail.setFinalScore("60");
                    }else if (appraiseResultDetail.getQuotaCode().equals("ZW_PZ_25")) {
                        appraiseResultDetail.setEvaluationScore("94");
                        appraiseResultDetail.setFinalScore("94");
                    } else if (appraiseResultDetail.getQuotaCode().equals("ZW_PZ_26")) {
                        appraiseResultDetail.setEvaluationScore("A");
                        appraiseResultDetail.setFinalScore("A");
                    } else {
                        appraiseResultDetail.setEvaluationScore("0");
                        appraiseResultDetail.setFinalScore("0");
                        if (appraiseResultDetail.getQuotaCode().equals("ZW_JS_01")|| appraiseResultDetail.getQuotaCode().equals("ZW_FW_01")) {
                            if (Strings.isNullOrEmpty(strVal)) {
                                strVal = "0";
                            }else{
                                appraiseResultDetail.setEvaluationScore(strVal);
                                appraiseResultDetail.setFinalScore(strVal);
                            }
                        }
                    }
                    inserLists.add(appraiseResultDetail);
                }
                supAppraisePlanSupplierService.saveOrUpdate(appraisePlanSupplier);
                supplierPlanIds.add(supplierPlanId);
            }
            inserLists.addAll(supplierDetail.values());
            if (CollectionUtil.isNotEmpty(inserLists)) {
                supAppraiseResultDetailService.saveBatch(inserLists);
            }
//            calculateProcesser(ap);
        } catch (FileNotFoundException e) {
            throw new DaoException("文件不存在");
        }
    }

    private void calculateProcesser(SupAppraisePlan supAppraisePlan) {
        List<PlanSupplierCalPO> list = supAppraisePlanSupplierService.findForCalculate(supAppraisePlan.getId());
        for (PlanSupplierCalPO planSupplierCalDto : list) {
            calSysGet(planSupplierCalDto);
        }
    }

    private void calSysGet(PlanSupplierCalPO planSupplierCalDto) {

        final Integer evaluationCycle = planSupplierCalDto.getEvaluationCycle();
        final Integer year = planSupplierCalDto.getYear();
        final Long supplierId = planSupplierCalDto.getSupplierId();
        final Long planSupplierId = planSupplierCalDto.getPlanSupplierId();
        Map<String, Object> params = Maps.newHashMap();
        params.put("year", year);
        Map<String, Object> evnMap = Maps.newHashMap();
        evnMap.put("evaluationCycle", evaluationCycle);
        params.put("supplierId", supplierId);
        evnMap.putAll(params);
        final List<SupAppraiseResultDetail> importAppraiseDetail = getQuotaByType(planSupplierId, QuotaType.IMPORT);
        for (SupAppraiseResultDetail appraiseResultDetail : importAppraiseDetail) {
            evnMap.put("Total" + appraiseResultDetail.getDimensionCode(), appraiseResultDetail.getDimensionTotal());
            evnMap.put("Weight" + appraiseResultDetail.getDimensionCode(), appraiseResultDetail.getDimensionWeight());
            params.put("Weight" + appraiseResultDetail.getDimensionCode(), appraiseResultDetail.getDimensionWeight());
            params.put("planId", appraiseResultDetail.getPlanId());
            setEvnParams(evnMap, appraiseResultDetail);

        }
        final List<SupAppraiseResultDetail> importAppraiseDetail1MQ = getQuotaByType(planSupplierId,
                QuotaType.MANUAL_QUOTA);
        for (SupAppraiseResultDetail appraiseResultDetail : importAppraiseDetail1MQ) {
            evnMap.put("Total" + appraiseResultDetail.getDimensionCode(), appraiseResultDetail.getDimensionTotal());
            evnMap.put("Weight" + appraiseResultDetail.getDimensionCode(), appraiseResultDetail.getDimensionWeight());
            params.put("Weight" + appraiseResultDetail.getDimensionCode(), appraiseResultDetail.getDimensionWeight());
            params.put("planId", appraiseResultDetail.getPlanId());
            setEvnParams(evnMap, appraiseResultDetail);
        }
        /**
         * 取到所有需要从系统取值的指标根据供应商计划id
         */
        List<SupAppraiseResultDetail> appraiseResultDetailList = getQuotaByType(planSupplierId, QuotaType.SYS_GET);
        for (SupAppraiseResultDetail appraiseResultDetail : appraiseResultDetailList) {
            evnMap.put("Total" + appraiseResultDetail.getDimensionCode(), appraiseResultDetail.getDimensionTotal());
            evnMap.put("Weight" + appraiseResultDetail.getDimensionCode(), appraiseResultDetail.getDimensionWeight());
            params.put("Weight" + appraiseResultDetail.getDimensionCode(), appraiseResultDetail.getDimensionWeight());
            params.put("planId", appraiseResultDetail.getPlanId());
            final String calculationFormula = appraiseResultDetail.getCalculationFormula();
            if (Strings.isNullOrEmpty(calculationFormula)) {
                continue;
            }
            Object value = supAppraiseResultDetailService.findVal(calculationFormula, params);
            if (Objects.isNull(value)) {
                value = BigDecimal.valueOf(0);
            }
            appraiseResultDetail.setEvaluationScore(value.toString());
            appraiseResultDetail.setFinalScore(value.toString());
            setEvnParams(evnMap, appraiseResultDetail);
            supAppraiseResultDetailService.updateById(appraiseResultDetail);
        }

        List<SupAppraiseResultDetail> appraiseResultDetails = getQuotaByType(planSupplierId, QuotaType.FORMULA);
        for (SupAppraiseResultDetail appraiseResultDetail : appraiseResultDetails) {
            evnMap.put("Total" + appraiseResultDetail.getDimensionCode(), appraiseResultDetail.getDimensionTotal());
            evnMap.put("Weight" + appraiseResultDetail.getDimensionCode(), appraiseResultDetail.getDimensionWeight());
            params.put("Weight" + appraiseResultDetail.getDimensionCode(), appraiseResultDetail.getDimensionWeight());
            params.put("planId", appraiseResultDetail.getPlanId());
            final String calculationFormula = appraiseResultDetail.getCalculationFormula();
            if (Strings.isNullOrEmpty(calculationFormula)) {
                continue;
            }
            final Double maxScore = Objects.isNull(
                    appraiseResultDetail.getMaxScore()) ? 0 : appraiseResultDetail.getMaxScore();
            evnMap.put("maxScore", maxScore);
            String strVal = "";
            try {
                final Object execute = AviatorEvaluator.execute(calculationFormula.replace(StrUtil.SPACE, ""), evnMap);
                strVal = getStrVal(execute);
            } catch (Exception e) {
                e.printStackTrace();
                throw new DaoException(StrUtil.format("{}:表达式错误!", calculationFormula));
            }
            appraiseResultDetail.setFinalScore(strVal);
            appraiseResultDetail.setEvaluationScore(strVal);
            setEvnParams(evnMap, appraiseResultDetail);
            supAppraiseResultDetailService.updateById(appraiseResultDetail);
        }
    }

    public List<SupAppraiseResultDetail> getQuotaByType(Long planSupplierId, QuotaType quotaType) {
        return supAppraiseResultDetailService.list(
                new LambdaQueryWrapper<SupAppraiseResultDetail>().eq(SupAppraiseResultDetail::getSupplierPlanId,
                        planSupplierId).eq(SupAppraiseResultDetail::getQuotaType, quotaType.getValue()));
    }

    private void setEvnParams(Map<String, Object> evnMap, SupAppraiseResultDetail appraiseResultDetail)
    {
        if (NumberUtil.isNumber(appraiseResultDetail.getFinalScore())) {
            evnMap.put(appraiseResultDetail.getQuotaCode(), new BigDecimal(appraiseResultDetail.getFinalScore()));
        } else {
            if (Strings.isNullOrEmpty(appraiseResultDetail.getFinalScore())) {
                evnMap.put(appraiseResultDetail.getQuotaCode(), BigDecimal.valueOf(0));
            } else {
                evnMap.put(appraiseResultDetail.getQuotaCode(), appraiseResultDetail.getFinalScore());
            }
        }
    }

    private String getStrVal(Object o) {
        if (o instanceof Double) {
            Double a = (Double) o;
            if (Double.isNaN(a) || Double.isInfinite(a)) {
                return "0";
            }
            return String.valueOf(a);
        } else if (o instanceof Integer) {
            return String.valueOf(o);
        } else if (o instanceof Float) {
            Float a = (Float) o;
            if (Float.isNaN(a) || Float.isInfinite(a)) {
                return "0";
            }
            return String.valueOf(a);
        } else if (Objects.isNull(o)) {
            return StrUtil.EMPTY;
        } else {
            return o.toString();
        }
    }

}