package com.jiayue.ipfcst.console.service;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.jiayue.ipfcst.common.core.exception.BusinessException;
import com.jiayue.ipfcst.common.core.util.CommonUtil;
import com.jiayue.ipfcst.common.core.util.DateMomentUtil;
import com.jiayue.ipfcst.common.core.util.DateTimeUtil;
import com.jiayue.ipfcst.common.data.constant.enums.ElectricFieldTypeEnum;
import com.jiayue.ipfcst.common.data.constant.enums.PredictionModelEnum;
import com.jiayue.ipfcst.common.data.entity.*;
import com.jiayue.ipfcst.common.data.repository.*;
import com.jiayue.ipfcst.common.data.service.BaseService;
import com.sun.istack.internal.NotNull;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.time.DateFormatUtils;
import org.apache.commons.lang.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 超短期功率预测业务
 *
 * @author xsl
 * @version 3.0
 * @since 2020/4/22 18:24
 */
@Service
@Slf4j
public class ForecastPowerUltraShortTermOneService extends BaseService {
  @Autowired
  ElectricFieldService electricFieldService;
  @Autowired
  ForecastPowerShortTermOneRepository forecastPowerShortTermOneRepository;
  @Autowired
  SysParameterService sysParameterService;
  @Autowired
  PowerStationStatusDataOneRepository powerStationStatusDataOneRepository;
  @Autowired
  ForecastPowerUltraShortTermOneRepository forecastPowerUltraShortTermOneRepository;
  @Autowired
  ForecastPowerUltraShortTermOneHisRepository forecastPowerUltraShortTermOneHisRepository;
  @Autowired
  ManualInterventionService manualInterventionService;
  @Autowired
  ForecastPowerShortTermOneService forecastPowerShortTermOneService;
  @Autowired
  ManualInterventionRatioService manualInterventionRatioService;

//  @Autowired
//  UltraShortTermCoefficientRepository ultraShortTermCoefficientRepository;
//  @Autowired
//  RepairPlanRepository repairPlanRepository;


  /**
   * 生成超短期预测功率,自动更新覆盖预测功率
   *
   * @param startTime 开始时间
   * @param endTime   结束时间
   */
  @Transactional(propagation = Propagation.REQUIRED)
  public void buildForecastPowerUltraShortTerm(@NotNull final Long startTime, @NotNull final Long endTime) {
    this.getForecastPowerUltraShortTerm(startTime, endTime);
  }
  /**
   * 获取超短期预测功率，当数据库中超短期预测记录不足查询所需时，进行本地化计算，用于上报专用
   *
   * @param startTime 开始时间
   * @param endTime   结束时间
   * @return 预测功率结果集
   */
  @SuppressWarnings("WeakerAccess")
  @Transactional(propagation = Propagation.REQUIRED)
  public List<ForecastPowerUltraShortTermOneHis> getForecastPowerUltraShortTerm(@NotNull final Long startTime, @NotNull final Long endTime) {
    log.info("开始获取超短期实时预测功率" + DateFormatUtils.format(startTime, "yyyy-MM-dd HH:mm:ss") + " 至 " + DateFormatUtils.format(endTime, "yyyy-MM-dd HH:mm:ss"));

    Long monentTime = 0L;
    try {
      monentTime = DateMomentUtil.getMomentTime(new Date().getTime(), 1, 15 * 60 * 1000L);
    } catch (Exception e) {
      log.error("获取当前时刻错误",e);
    }
    //为了保证回传和超短期数据一直，当数据库中有预测数据时，直接返回数据
    List<ForecastPowerUltraShortTermOneHis> byForecastTimeBetweenAndGenDate = this.forecastPowerUltraShortTermOneHisRepository.findByForecastTimeBetweenAndGenDate(startTime, endTime, new Date(monentTime));


    int moment = DateMomentUtil.getIntervalMoment(startTime, endTime,15*60*1000l);


    if (byForecastTimeBetweenAndGenDate.size() >= moment) {
      return byForecastTimeBetweenAndGenDate;
    }


    // 查询场站信息
    ElectricField electricFieldInfo = electricFieldService.get();
    electricFieldInfo.setElectricFieldTypeEnum(ElectricFieldTypeEnum.E2);
    electricFieldInfo.setCapacity(new BigDecimal(electricFieldInfo.getBackupF()));
    // 查询预测时间点对应的开机容量
    Map<Long, BigDecimal> openCapacityMap = null;
    try {
      openCapacityMap = super.queryOpenCapacityOne(startTime, endTime, electricFieldInfo.getCapacity());
    } catch (BusinessException e) {
      log.error("预测数据生成获取开机容量出错：" + CommonUtil.printStackTraceToString(e));
    }


    List<ForecastPowerUltraShortTermOne> forecastPowerUltraShortTermList = new ArrayList<>();
    List<ForecastPowerUltraShortTermOne> tempList = this.forecastPowerUltraShortTermOneRepository.findByForecastTimeBetween(startTime, endTime);
    for (ForecastPowerUltraShortTermOne f:tempList){
      if (Integer.parseInt(DateFormatUtils.format(f.getForecastTime(),"mm"))%15==0){
        forecastPowerUltraShortTermList.add(f);
      }
    }

    Long momentTime = 15 * 60 * 1000L; // 15分钟一个时刻
    Integer moments = Math.toIntExact((endTime - startTime) / momentTime + 1);
    log.info("获取所需记录数:" + moments);

    if (moments > forecastPowerUltraShortTermList.size()) {
      Map<Long, List<ForecastPowerUltraShortTermOne>> forecastPowerShortTermsMap = forecastPowerUltraShortTermList.stream().collect(Collectors.groupingBy(ForecastPowerUltraShortTermOne::getForecastTime));
      for (Long tempTime = startTime; tempTime <= endTime; tempTime = tempTime + momentTime) {
        if (forecastPowerShortTermsMap.get(tempTime) == null) {
          log.info("文件超短期缺点："+tempTime+" forecastPowerShortTermsMap里个数:"+forecastPowerShortTermsMap.size());
          BigDecimal tempValue;
          if (ElectricFieldTypeEnum.E1.equals(electricFieldInfo.getElectricFieldTypeEnum())) {
            if (DateTimeUtil.checkInSunriseAndSunset(startTime, electricFieldInfo.getLongitude().doubleValue(), electricFieldInfo.getLatitude().doubleValue())) {
              tempValue = new BigDecimal(CommonUtil.getRandom(1, 70) / 100.0d);
            } else {
              // 日升日落
              tempValue = BigDecimal.ZERO;
            }
          } else {
            tempValue = new BigDecimal(CommonUtil.getRandom(1, 70) / 100.0d);
          }
          tempValue = tempValue.multiply(electricFieldInfo.getCapacity()).setScale(2, BigDecimal.ROUND_HALF_UP);
          ForecastPowerUltraShortTermOne forecastPowerUltraShortTerm = new ForecastPowerUltraShortTermOne();
          forecastPowerUltraShortTerm.setGenDate(new Date(monentTime));
          forecastPowerUltraShortTerm.setForecastTime(tempTime);
          forecastPowerUltraShortTerm.setFpValue(tempValue);
          forecastPowerUltraShortTerm.setPredictionModelEnum(PredictionModelEnum.E4);
          forecastPowerUltraShortTerm.setCoefficientValue(new BigDecimal(-0.99).setScale(2,BigDecimal.ROUND_HALF_UP));
          forecastPowerUltraShortTerm.setDifferenceValue(new BigDecimal(-0.99).setScale(2,BigDecimal.ROUND_HALF_UP));
          // 保存超短期实时预测记录
          this.forecastPowerUltraShortTermOneRepository.save(forecastPowerUltraShortTerm);
          forecastPowerUltraShortTermList.add(forecastPowerUltraShortTerm);
        }
      }
    }
    log.info("生成超短期实时预测功率记录数:" + forecastPowerUltraShortTermList.size());
    // 按预测时刻升序
    forecastPowerUltraShortTermList.sort(Comparator.comparing(ForecastPowerUltraShortTermOne::getForecastTime));

//    int qn_yth = sysParameterService.getTranSysParameter("qn_yth", "0");
//
//    if(qn_yth != 0){
//      //一体化消减
//      List<RepairPlan> list = repairPlanRepository.findAll();
//      if(list.size()>0){
//        log.info("===========执行一体化对超短期上报数据调整（消减容量）");
//        for (int i = 0; i < forecastPowerUltraShortTermList.size(); i++) {
//          ForecastPowerUltraShortTerm forecastPowerUltraShortTerm = forecastPowerUltraShortTermList.get(i);
//          List<RepairPlan> collect = list.stream().filter(r -> r.getStartTime().getTime() <= forecastPowerUltraShortTerm.getForecastTime() && forecastPowerUltraShortTerm.getForecastTime() < r.getEndTime().getTime()).collect(Collectors.toList());
//          if(collect.size()>0){
//
//            BigDecimal capacityCurtailment = collect.get(0).getCapacityCurtailment();
//            BigDecimal fpValue = forecastPowerUltraShortTermList.get(i).getFpValue();
//
//            //消减后的容量
//            BigDecimal subtract = fpValue.subtract(capacityCurtailment);
//            if(subtract.compareTo(new BigDecimal(0)) <= 0){
//              subtract = new BigDecimal(0);
//            }
//            forecastPowerUltraShortTermList.get(i).setFpValue(subtract);
//            log.info("一体化对超短期上报数据调整=》时间：{};消减容量为：{};调整前：{};调整后：{}", DateFormatUtils.format(forecastPowerUltraShortTermList.get(i).getForecastTime(),"yyyy-MM-dd HH:mm"),capacityCurtailment, fpValue, subtract);
//          }
//
//        }
//        log.info("===========结束一体化对超短期上报数据调整（消减容量）");
//      }
//
//
//
//      List<UltraShortTermCoefficient> ultraShortTermCoefficientList = ultraShortTermCoefficientRepository.findByParseTimeBetween(new Date(startTime-2*15*60*1000l), new Date(startTime-15*60*1000l));
//
//      if(ultraShortTermCoefficientList.size()>0){
//        log.info("===========执行一体化对超短期上报数据调整（系数）");
//        for (int i = 0; i < forecastPowerUltraShortTermList.size(); i++) {
//          ForecastPowerUltraShortTerm forecastPowerUltraShortTerm = forecastPowerUltraShortTermList.get(i);
//          List<UltraShortTermCoefficient> collect = ultraShortTermCoefficientList.stream().filter(u -> u.getTime().getTime() == forecastPowerUltraShortTerm.getForecastTime()).collect(Collectors.toList());
//
//          if(collect.size()>0){
//            BigDecimal coefficient = collect.get(0).getCoefficient();
//            BigDecimal fpValue = forecastPowerUltraShortTermList.get(i).getFpValue();
//            BigDecimal coefficientAfter = fpValue.multiply(coefficient).setScale(2,BigDecimal.ROUND_DOWN);
//
//            forecastPowerUltraShortTermList.get(i).setFpValue(coefficientAfter);
//            log.info("一体化对超短期上报数据调整=》时间：{};系数为：{};调整前：{};调整后：{}", DateFormatUtils.format(forecastPowerUltraShortTermList.get(i).getForecastTime(),"yyyy-MM-dd HH:mm"),coefficient, fpValue, coefficientAfter);
//          }
//        }
//        log.info("===========结束一体化对超短期上报数据调整（系数）");
//      }
//    }
//
//


    // 处理超短期历史记录
    List<ForecastPowerUltraShortTermOneHis> forecastPowerUltraShortTermHiss = new ArrayList<>();

    ForecastPowerUltraShortTermOneHis forecastPowerUltraShortTermHis;
    int n = 1;
    // 生成超短期历史数据
    BigDecimal openCapacity;
    //生成数据
    for (ForecastPowerUltraShortTermOne forecastPowerUltraShortTerm : forecastPowerUltraShortTermList) {
      forecastPowerUltraShortTermHis = new ForecastPowerUltraShortTermOneHis();
      openCapacity = openCapacityMap.get(forecastPowerUltraShortTerm.getForecastTime());
      forecastPowerUltraShortTermHis.setForecastTime(forecastPowerUltraShortTerm.getForecastTime());
      forecastPowerUltraShortTermHis.setSuCapacity(openCapacity);
      forecastPowerUltraShortTermHis.setCapacity(electricFieldInfo.getCapacity());
      forecastPowerUltraShortTermHis.setForecastHowLongAgo(n++);
      forecastPowerUltraShortTermHis.setTheoryValue(forecastPowerUltraShortTerm.getFpValue());
      // 预测可用功率=预测*（开机容量/装机容量）
      BigDecimal fpValue = forecastPowerUltraShortTerm.getFpValue().multiply(openCapacity)
        .divide(electricFieldInfo.getCapacity(), 2, BigDecimal.ROUND_HALF_UP);
      forecastPowerUltraShortTermHis.setAbleValue(fpValue);
      forecastPowerUltraShortTermHis.setPredictionModelEnum(forecastPowerUltraShortTerm.getPredictionModelEnum());
      forecastPowerUltraShortTermHis.setDifferenceValue(forecastPowerUltraShortTerm.getDifferenceValue());
      forecastPowerUltraShortTermHis.setCoefficientValue(forecastPowerUltraShortTerm.getCoefficientValue());
      forecastPowerUltraShortTermHis.setGenDate(new Date(monentTime));
      forecastPowerUltraShortTermHiss.add(forecastPowerUltraShortTermHis);
    }
//    List<ForecastPowerUltraShortTermHis> forecastPowerUltraShortTermHiss = forecastPowerUltraShortTermHiss1.stream().filter(t -> t.getForecastHowLongAgo() <=16).collect(Collectors.toList());
    // 获取实际功率替换超短期点位参数
    Integer replacePoint = 0;
    String realpower_replace_cdq = sysParameterService.getSysParameter("realpower_replace_cdq", "0");
    replacePoint = Integer.valueOf(realpower_replace_cdq);
    if (replacePoint <= forecastPowerUltraShortTermHiss.size() && replacePoint > 0) {
      Long pre5Time = 0l;
      Date systemDate = new Date();
      try {
        // 获取前5分钟时刻
        pre5Time = DateMomentUtil.getMomentTime(systemDate.getTime() - 5 * 60 * 1000, 1, 5 * 60 * 1000L);
      } catch (Exception e) {
        log.error("超短期数据用实际功率替换生成时刻步长错误", e);
        pre5Time = DateMomentUtil.getDayStartTime(systemDate.getTime());
      }
      List<PowerStationStatusDataOne> realPowerList = powerStationStatusDataOneRepository.findByTimeBetween(new Date(pre5Time), new Date(pre5Time + 5 * 60 * 1000));
      if (realPowerList.size() > 0) {
        // 按时间降序排列
        realPowerList.sort(Comparator.comparing(PowerStationStatusDataOne::getTime).reversed());
        // 获取最后一条最新的实际功率
        PowerStationStatusDataOne realPower = realPowerList.get(0);
        // 将实际功率替换到对应的超短期点位上
        ForecastPowerUltraShortTermOneHis d = forecastPowerUltraShortTermHiss.get(replacePoint - 1);
        if (realPower.getRealValue().compareTo(new BigDecimal(0)) != -1) {
          d.setAbleValue(realPower.getRealValue());
        }
      }
    }

    //-----------------------------------------------------开始进行人工干预数值的判断----------------------------------------------------
    //-----------------------------------------------------点位判断开始----------------------------------------------------
//    List<ManualInterventionData> manualInterventionDataList = manualInterventionService.queryManualIntervention(startTime, endTime, "1");
//    manualInterventionDataList.sort(Comparator.comparing(ManualInterventionData::getInterveneTime));
//    Map<Long, BigDecimal> mMap = new HashMap<>();
//    int flag = 0;
//    if (manualInterventionDataList.size() > 0) {
//      for (ManualInterventionData manualInterventionData : manualInterventionDataList) {
//        mMap.put(manualInterventionData.getInterveneTime(), manualInterventionData.getInterveneData());
//      }
//      for (ForecastPowerUltraShortTermOneHis forecastPowerUltraShortTermHis1 : forecastPowerUltraShortTermHiss) {
//        BigDecimal ma = mMap.get(forecastPowerUltraShortTermHis1.getForecastTime());
//        if (ma != null) {
//          forecastPowerUltraShortTermHis1.setAbleValue(ma.setScale(2, BigDecimal.ROUND_HALF_UP));
//          forecastPowerUltraShortTermHis1.setTheoryValue(ma.setScale(2, BigDecimal.ROUND_HALF_UP));
//          forecastPowerUltraShortTermHis1.setGenDate(new Date(monentTime));
//          forecastPowerUltraShortTermHis1.setPredictionModelEnum(PredictionModelEnum.E6);
//          forecastPowerUltraShortTermHiss.set(flag, forecastPowerUltraShortTermHis1);
//        }
//        flag++;
//      }
//    }
    //-----------------------------------------------------点位判断结束----------------------------------------------------
    //-----------------------------------------------------系数判断开始----------------------------------------------------
    //获取今日凌晨00:00
//    long mStartTime = DateUtil.beginOfDay(DateTime.now()).getTime();
//    long mEndTime = mStartTime + 24*60*60*1000l - 1000;
//    List<ManualInterventionRatioData> manualInterventionRatioDataList = manualInterventionRatioService.queryManualInterventionRatio(mStartTime, mEndTime, "1");
//
//    //如果有人工干预系数设置记录
//    if(manualInterventionRatioDataList.size() > 0){
//      //循环所有记录
//      for(ManualInterventionRatioData manualInterventionRatioData :manualInterventionRatioDataList){
//        for (Long tempTime = manualInterventionRatioData.getInterveneStartTime(); tempTime <= manualInterventionRatioData.getInterveneEndTime(); tempTime = tempTime + 15 * 60 * 1000L) {
//          //循环所有超短期的值
//          int mrflag = 0;
//          for (ForecastPowerUltraShortTermOneHis forecastPowerUltraShortTermHis1 : forecastPowerUltraShortTermHiss) {
//            //如果该时间设置了系数则数值*系数
//            if(forecastPowerUltraShortTermHis1.getForecastTime().equals(tempTime)){
//              BigDecimal ableValue = forecastPowerUltraShortTermHis1.getAbleValue().multiply(new BigDecimal(manualInterventionRatioData.getRatio().toString())).setScale(2, BigDecimal.ROUND_HALF_UP);
//              //如果计算后的数据大于装机容量 则ableValue=装机容量
//              if((ableValue).compareTo(new BigDecimal(electricFieldInfo.getCapacity().toString())) > 0){
//                ableValue = new BigDecimal(electricFieldInfo.getCapacity().toString());
//              }
//              forecastPowerUltraShortTermHis1.setAbleValue(ableValue);
//              forecastPowerUltraShortTermHis1.setTheoryValue(ableValue);
//              forecastPowerUltraShortTermHis1.setGenDate(new Date(monentTime));
//              forecastPowerUltraShortTermHis1.setPredictionModelEnum(PredictionModelEnum.E10);
//              forecastPowerUltraShortTermHiss.set(mrflag, forecastPowerUltraShortTermHis1);
//            }
//            mrflag++;
//          }
//        }
//      }
//    }
    //-----------------------------------------------------系数判断结束----------------------------------------------------



    String lowerPredictionLimit = super.getSysParameter("LowerPredictionLimit", "0");
    BigDecimal lpl = new BigDecimal(lowerPredictionLimit);

    forecastPowerUltraShortTermHiss.forEach(s->{
      if(s.getAbleValue().compareTo(lpl)==-1){
        s.setAbleValue(lpl);
      }
    });
    // 获取当前时刻标记时间
//    Long nowMomentTime;
//    try {
//      nowMomentTime = DateMomentUtil.getMomentTime(System.currentTimeMillis(), 1, 15 * 60 * 1000L);
//    } catch (Exception e) {
//      log.error("时刻步长错误", e);
//      nowMomentTime = DateMomentUtil.getDayStartTime(System.currentTimeMillis());
//    }

    //-----------------------------------------------------浙江光伏负偏差---------------------------------------------------

    try {
      String negative_deviation = super.getSysParameter("negative_deviation", "0");
      if (electricFieldInfo.getProvinceEnum().toString().equals("E33")&&electricFieldInfo.getElectricFieldTypeEnum().toString().equals("E1")&&!negative_deviation.equals("0")&&!negative_deviation.equals("")){
        int mrflag = 0;
        for (ForecastPowerUltraShortTermOneHis f : forecastPowerUltraShortTermHiss) {
          f.setAbleValue(f.getAbleValue().subtract(new BigDecimal(negative_deviation)));
          f.setTheoryValue(f.getTheoryValue().subtract(new BigDecimal(negative_deviation)));
          f.setGenDate(new Date());
          f.setPredictionModelEnum(PredictionModelEnum.E10);
          forecastPowerUltraShortTermHiss.set(mrflag, f);
          mrflag++;
        }
      }
    }catch (Exception e){
      e.printStackTrace();
      log.info("负偏差计算错误，请检查negative_deviation参数是否为数字");
    }
    //-----------------------------------------------------浙江光伏负偏差---------------------------------------------------
    //-----------------------------------------------------人工干预数据判断结束----------------------------------------------------
    // 删除当前时刻标记时间生成的超短期历史记录
    this.forecastPowerUltraShortTermOneHisRepository.deleteNowMoment(startTime, endTime, new Date(monentTime));
    // 保存超短期历史记录
    this.forecastPowerUltraShortTermOneHisRepository.saveAll(forecastPowerUltraShortTermHiss);
    return forecastPowerUltraShortTermHiss;
  }

  /**
   * 执行超短期预测
   */
  @Transactional(propagation = Propagation.REQUIRED, rollbackFor = RuntimeException.class)
  public void executeForecast() {
    // 根据场站类型执行相应超短期预测
    try {
      // 获取查询时间，从当前时间所处时间点标记时间开始查询，截至到96个时间点对应的标记时间
      String cdqUpMin = super.getSysParameter("CDQ_UP_MIN", "0");
      Long calTime = DateMomentUtil.getMomentTime(System.currentTimeMillis() + Integer.parseInt(cdqUpMin) * 1000 * 60, 1, 15 * 60 * 1000L);
      Long startTime = calTime + 15 * 1000 * 60L;
      String llcdq_point = super.getSysParameter("FILE_LLCDQ_POINT", "16");
      Integer forecastPoints = Integer.parseInt(llcdq_point);
      Integer forecastMinutes = forecastPoints * 15;
      // 结束时间增加15分钟为了防止文件先生成，实时表中最后一个时间点没有点位的问题
      Long endTime = DateUtils.addMinutes(new Date(startTime), forecastMinutes).getTime();

      // 查询该时间段内的短期预测功率
      List<ForecastPowerShortTermOne> forecastPowerShortTermList = this.forecastPowerShortTermOneRepository.findByForecastTimeBetween(startTime, endTime);

      Map<Long, List<ForecastPowerShortTermOne>> forecastPowerShortTermsMap =
        forecastPowerShortTermList.stream().collect(Collectors.groupingBy(ForecastPowerShortTermOne::getForecastTime));
      // 查询场站信息
      ElectricField electricField = this.getElectricField();
      electricField.setElectricFieldTypeEnum(ElectricFieldTypeEnum.E2);
      electricField.setCapacity(new BigDecimal(electricField.getBackupF()));
      Map<Long, BigDecimal> openCapacityMap = null;
      try {
        openCapacityMap = super.queryOpenCapacityOne(startTime, endTime, electricField.getCapacity());
      } catch (BusinessException e) {
        log.error("预测数据生成获取开机容量出错：" + CommonUtil.printStackTraceToString(e));
      }
      List<ForecastPowerShortTermOne> addForecastPowerShortTermList = new ArrayList<>();
      // 判断短期数据是否缺点
      for (Long tempTime = startTime; tempTime <= endTime; tempTime = tempTime + 15 * 60 * 1000L) {
        if (forecastPowerShortTermsMap.get(tempTime) == null) {
          // 缺失时间点
          ForecastPowerShortTermOne forecastPowerShortTerms = null;
          if (ElectricFieldTypeEnum.E1.compareTo(electricField.getElectricFieldTypeEnum()) == 0) {
            forecastPowerShortTerms = forecastPowerShortTermOneService.generateSolarPowerShortTerm(tempTime, openCapacityMap.get(tempTime), electricField);
          } else {
            forecastPowerShortTerms = forecastPowerShortTermOneService.generateWindPowerShortTerm(tempTime, openCapacityMap.get(tempTime));
          }
          addForecastPowerShortTermList.add(forecastPowerShortTerms);
        }
      }
      if (!addForecastPowerShortTermList.isEmpty()) {
        // 保存短期预测
        this.forecastPowerShortTermOneRepository.saveAll(addForecastPowerShortTermList);
        // 将补齐的预测功率追加到查询预测功率结果集中
        forecastPowerShortTermList.addAll(addForecastPowerShortTermList);
      }
      forecastPowerShortTermList.sort(Comparator.comparing(ForecastPowerShortTermOne::getForecastTime));

      if (ElectricFieldTypeEnum.E1.compareTo(electricField.getElectricFieldTypeEnum()) == 0) {
        // 光伏电站
        this.executeForecastForlight(forecastPowerShortTermList, electricField.getCapacity());
      } else if (ElectricFieldTypeEnum.E2.compareTo(electricField.getElectricFieldTypeEnum()) == 0) {
        // 风力电场
        this.executeForecastForWind(forecastPowerShortTermList, electricField.getCapacity());
      } else {
        log.error("场站类型非法！");
      }
    } catch (BusinessException e) {
      log.error("获取场站信息出错！", e);
    } catch (Exception e) {
      log.error("系统运行错误！", e);
    }
  }

  /**
   * 执行风电场超短期预测
   *
   * @param forecastPowerShortTermList 短期预测结果集
   * @param capacity                   装机容量
   */
  private List<ForecastPowerUltraShortTermOne> executeForecastForWind(final List<ForecastPowerShortTermOne> forecastPowerShortTermList, final BigDecimal capacity) {
    List<ForecastPowerUltraShortTermOne> forecastPowerUltraShortTermList = new ArrayList<>();
    ForecastPowerUltraShortTermOne forecastPowerUltraShortTerm;
    //获取系统参数cdqjsfs，超短期计算方式，0为默认乘系数的方式，1为根据可用功率计算的方式
    String cdqjsfs = electricFieldService.getSysParameter("cdqjsfs", "1");
    log.info("参数cdqjsfs值为：" + cdqjsfs + "，超短期计算方式，0为默认乘系数的方式，1为根据可用功率计算的方式。");
    BigDecimal stPower, ustPower,ustPowers;
    // 查询当前时间点标记时间前10分钟的可用功率
    Date currentTime = new Date(System.currentTimeMillis());
    Date startTime = DateUtils.addMinutes(currentTime, -10);
    Date endTime = DateUtils.addMinutes(currentTime, 1);
    List<PowerStationStatusDataOne> powerStationStatusDataList = this.powerStationStatusDataOneRepository.findByTimeBetween(startTime, endTime);
    List<PowerStationStatusDataOne> filterList = powerStationStatusDataList.stream().filter(t -> t.getAbleValue().compareTo(new BigDecimal("-1")) == 1).collect(Collectors.toList());
    String coe = super.getSysParameter("CDQ_COE", "1.05");

    Long monentTime = 0L;
    try {
      monentTime = DateMomentUtil.getMomentTime(new Date().getTime(), 1, 15 * 60 * 1000L);
    } catch (Exception e) {
      log.error("获取当前时刻错误",e);
    }
    if (filterList.size() > 0) {
      // 获取当前时刻对应的短期
      List<ForecastPowerShortTermOne> currentForecastPowerShortTermList;
      BigDecimal currentForecastPowerValue = BigDecimal.ZERO;
      try {
        Long currentMoment = DateMomentUtil.getMomentTime(currentTime.getTime(), 1, 15 * 60 * 1000L);
        currentForecastPowerShortTermList = this.forecastPowerShortTermOneRepository.findByForecastTimeBetween(currentMoment, currentMoment);
        if (currentForecastPowerShortTermList.size()>0){
          currentForecastPowerValue = currentForecastPowerShortTermList.get(0).getFpValue();
        }
        else{
          // 当前时间没有对应的短期，用实际功率最近的一个替换
          filterList.sort(Comparator.comparing(PowerStationStatusDataOne::getTime).reversed());
          currentForecastPowerValue = filterList.get(0).getAbleValue();
        }
      } catch (Exception e) {
        e.printStackTrace();
      }

      BigDecimal sumAbleValue = filterList.stream().map(PowerStationStatusDataOne::getAbleValue)
        .reduce(BigDecimal.ZERO, BigDecimal::add);
      BigDecimal averageAbleValue = sumAbleValue.divide(new BigDecimal(filterList.size()), 2, BigDecimal.ROUND_HALF_UP);
      //可用-短期差值
      BigDecimal deviationValue = averageAbleValue.subtract(currentForecastPowerValue);
      for (int i = 0; i < forecastPowerShortTermList.size(); i++) {
        forecastPowerUltraShortTerm = new ForecastPowerUltraShortTermOne();
        forecastPowerUltraShortTerm.setForecastTime(forecastPowerShortTermList.get(i).getForecastTime());
        forecastPowerUltraShortTerm.setGenDate(new Date(monentTime));
        //短期
        stPower = forecastPowerShortTermList.get(i).getFpValue();
        //短期*系数
        ustPowers = stPower.multiply(new BigDecimal(coe)).setScale(2, BigDecimal.ROUND_HALF_UP);
        // 如果短期预测小于等于0，则超短期为0
        if (stPower.doubleValue() <= 0) {
          forecastPowerUltraShortTerm.setFpValue(BigDecimal.ZERO);
          forecastPowerUltraShortTerm.setDifferenceValue(BigDecimal.ZERO);
          forecastPowerUltraShortTerm.setCoefficientValue(BigDecimal.ZERO);
          forecastPowerUltraShortTerm.setPredictionModelEnum(PredictionModelEnum.E4);
        } else {
          BigDecimal xzjdq = deviationValue.add(stPower).setScale(2, BigDecimal.ROUND_HALF_UP);
          String cdqjsfsZbxz = electricFieldService.getSysParameter("cdqjsfsZbxz", "0.4");
          log.debug("参数cdqjsfsZbxz值为：" + cdqjsfsZbxz + "，超短期计算方式，可用和短期的差值加短期占比。");
          String cdqjsfsZbdq = electricFieldService.getSysParameter("cdqjsfsZbdq", "0.6");
          log.debug("参数cdqjsfsZbdq值为：" + cdqjsfsZbdq + "，超短期计算方式，短期占比。");
          ustPower = xzjdq.multiply(new BigDecimal(cdqjsfsZbxz)).setScale(2, BigDecimal.ROUND_HALF_UP).add(stPower.multiply(new BigDecimal(cdqjsfsZbdq)).setScale(2, BigDecimal.ROUND_HALF_UP));
          if (ustPower.doubleValue() > capacity.doubleValue()) {
            // 如果超短期结果超出装机容量，则超短期结果为装机容量
            forecastPowerUltraShortTerm.setFpValue(capacity);
          } else if (ustPower.doubleValue() < 0) {
            // 如果超短期结果小于0，则超短期结果为0
            forecastPowerUltraShortTerm.setFpValue(BigDecimal.ZERO);
          }else{
            if(cdqjsfs.equals("1")){
              forecastPowerUltraShortTerm.setFpValue(ustPower);
              forecastPowerUltraShortTerm.setPredictionModelEnum(PredictionModelEnum.E5);
            }else{
              forecastPowerUltraShortTerm.setFpValue(ustPowers);
              forecastPowerUltraShortTerm.setPredictionModelEnum(PredictionModelEnum.E9);
            }
          }
          forecastPowerUltraShortTerm.setDifferenceValue(ustPower);
          forecastPowerUltraShortTerm.setCoefficientValue(ustPowers);
        }

        forecastPowerUltraShortTermList.add(forecastPowerUltraShortTerm);
      }
    } else {
      log.info("库中没有可用，本次可用计算数据采用短期*系数的方式生成数据");

      // 短期乘以系数
      for (int i = 0; i < forecastPowerShortTermList.size(); i++) {
        stPower = forecastPowerShortTermList.get(i).getFpValue();
        ustPower = stPower.multiply(new BigDecimal(coe)).setScale(2, BigDecimal.ROUND_HALF_UP);
        forecastPowerUltraShortTerm = new ForecastPowerUltraShortTermOne();
        forecastPowerUltraShortTerm.setForecastTime(forecastPowerShortTermList.get(i).getForecastTime());
        forecastPowerUltraShortTerm.setPredictionModelEnum(PredictionModelEnum.E9);
        forecastPowerUltraShortTerm.setCoefficientValue(ustPower);
        forecastPowerUltraShortTerm.setDifferenceValue(new BigDecimal(-0.99).setScale(2,BigDecimal.ROUND_HALF_UP));
        forecastPowerUltraShortTerm.setFpValue(ustPower);
        forecastPowerUltraShortTerm.setGenDate(new Date(monentTime));
        forecastPowerUltraShortTermList.add(forecastPowerUltraShortTerm);
      }
    }
    // 保存超短期预测结果
    this.forecastPowerUltraShortTermOneRepository.deleteByForecastTimeBetween(forecastPowerUltraShortTermList.get(0).getForecastTime(), forecastPowerUltraShortTermList.get(forecastPowerShortTermList.size()-1).getForecastTime());
    this.forecastPowerUltraShortTermOneRepository.saveAll(forecastPowerUltraShortTermList);

    return forecastPowerUltraShortTermList;
  }

  private void executeForecastForlight(final List<ForecastPowerShortTermOne> forecastPowerShortTermList, final BigDecimal capacity) {
    // 暂时光超短期预测方法=风超短期预测方法
    this.executeForecastForWind(forecastPowerShortTermList, capacity);
  }

}
