package com.jiayue.ipfcst.service;

import cn.hutool.core.date.DateUtil;
import com.jiayue.ipfcst.common.core.exception.BusinessException;
import com.jiayue.ipfcst.common.core.util.DateMomentUtil;
import com.jiayue.ipfcst.common.data.constant.enums.ElectricFieldTypeEnum;
import com.jiayue.ipfcst.common.data.entity.ElectricField;
import com.jiayue.ipfcst.common.data.entity.ForecastPowerShortTerm;
import com.jiayue.ipfcst.common.data.entity.ForecastPowerThroughoutTheYear;
import com.jiayue.ipfcst.common.data.entity.Nwp;
import com.jiayue.ipfcst.common.data.repository.ForecastPowerShortTermRepository;
import com.jiayue.ipfcst.common.data.repository.ForecastPowerThroughoutTheYearRepository;
import com.jiayue.ipfcst.common.data.service.BaseService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * 全年功率业务层
 *
 * @author shd
 * @version 1.0
 * @since 2022-03-31
 */
@Service
@Slf4j
@EnableScheduling
@RequiredArgsConstructor
public class ForecastPowerThroughoutTheYearService extends BaseService {
  private final ForecastPowerShortTermService forecastPowerShortTermService;
  private final ForecastPowerThroughoutTheYearRepository forecastPowerThroughoutTheYearRepository;
  private final ForecastPowerShortTermRepository forecastPowerShortTermRepository;
  private final NwpService nwpService;
  private final ElectricFieldService electricFieldService;


  /**
   * 全年功率预测
   *
   * @param startTime
   */
  @Transactional(propagation = Propagation.REQUIRED)
  public List<ForecastPowerThroughoutTheYear> ForecastPowerThroughoutTheYear(Long startTime,ElectricField electricField) {
    List<ForecastPowerThroughoutTheYear> forecastPowerThroughoutTheYearList = new ArrayList<>();
    List<Nwp> nwpList;
    BigDecimal sumNwp = new BigDecimal(0);
    BigDecimal nextMouthNwpVal;
    Calendar cal = Calendar.getInstance();
    cal.setTime(new Date(startTime));
    int month = DateMomentUtil.getMonth(startTime);
    int year = DateUtil.year(DateUtil.date(startTime));

    String yearMonth = year + "," + month;
    Long endTimeStr = startTime + 1000l * 60l * 60l * 24l * 7 - 1000l * 60l * 15l;
    List<ForecastPowerShortTerm> sendDataForTimeBetween = forecastPowerShortTermRepository.findByForecastTimeBetween(startTime, endTimeStr);
    ForecastPowerThroughoutTheYear forecastPowerThroughoutTheYear = new ForecastPowerThroughoutTheYear();
    //累计发电量公式  发电量= 预测值*0.25*0.1  累加96个点的发电量得出1天的累计发电量
    String[] datas;
    BigDecimal radio = new BigDecimal(0.025);
    BigDecimal sumValue = new BigDecimal(0);

    for (int i = 1; i <= 7; i++) {
      datas = forecastPowerShortTermService.findSendData(startTime + 1000 * 60 * 60 * 24 * (i - 1), startTime + 1000 * 60 * 60 * 24 * i - 1000 * 60 * 15, sendDataForTimeBetween);
      //预测发电量
      if (datas.length > 0) {
        BigDecimal value;
        for (String s : datas) {
          if (s != null) {
            value = new BigDecimal(s).multiply(radio).setScale(2, BigDecimal.ROUND_HALF_UP);
            sumValue = sumValue.add(value);
          }
        }
      } else {
        sumValue = sumValue.add(new BigDecimal(0));
      }
    }
    sumValue = sumValue.multiply(new BigDecimal(4.4));

    if (electricField.getElectricFieldTypeEnum().name().equals(ElectricFieldTypeEnum.E1.name())) {

      //计算月风速平均值
      for (int i = 0; i <= 12; i++) {
        // 设置为1号,当前日期既为本月第一天
        cal.set(Calendar.DAY_OF_MONTH, 1);
        long localStartTime = DateMomentUtil.getDayStartTime(cal.getTimeInMillis());
        // 获取当前月最后一天
        cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
        long endTime = DateMomentUtil.getDayLastTime(cal.getTimeInMillis());
        nwpList = nwpService.findByTimeBetween(localStartTime, endTime - 1000 * 60 * 15);
        cal.add(Calendar.MONTH, +1);
        if (nwpList.size() > 0) {
          BigDecimal nwp = new BigDecimal(0);
          //风速平均值
          for (Nwp n : nwpList) {
            nwp = nwp.add(n.getSwr());
          }
          sumNwp = nwp.divide(BigDecimal.valueOf(nwpList.size()), 2, BigDecimal.ROUND_HALF_UP);
        } else {
          forecastPowerThroughoutTheYear.setValue(new BigDecimal(0));
        }
      }

    } else{

      //计算月风速平均值
      for (int i = 0; i <= 12; i++) {
        // 设置为1号,当前日期既为本月第一天
        cal.set(Calendar.DAY_OF_MONTH, 1);
        long localStartTime = DateMomentUtil.getDayStartTime(cal.getTimeInMillis());
        // 获取当前月最后一天
        cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
        long endTime = DateMomentUtil.getDayLastTime(cal.getTimeInMillis());
        nwpList = nwpService.findByTimeBetween(localStartTime, endTime - 1000 * 60 * 15);
        cal.add(Calendar.MONTH, +1);
        if (nwpList.size() > 0) {
          BigDecimal nwp = new BigDecimal(0);
          //风速平均值
          for (Nwp n : nwpList) {
            nwp = nwp.add(n.getWs100());
          }
          sumNwp = nwp.divide(BigDecimal.valueOf(nwpList.size()), 2, BigDecimal.ROUND_HALF_UP);
        } else {
          forecastPowerThroughoutTheYear.setValue(new BigDecimal(0));
        }
      }
  }
    //生成日期
    cal.setTime(new Date());
    //实体赋值
    forecastPowerThroughoutTheYear.setFpValue(sumValue.setScale(2, BigDecimal.ROUND_HALF_UP));
    forecastPowerThroughoutTheYear.setGenDate(cal.getTime());
    forecastPowerThroughoutTheYear.setValue(sumNwp);
    forecastPowerThroughoutTheYear.setForecastTime(startTime);
    forecastPowerThroughoutTheYear.setYearMonth(yearMonth);
    forecastPowerThroughoutTheYearList.add(forecastPowerThroughoutTheYear);
    // 月之间上下波动20%
    // 下月预测功率
    BigDecimal nextMouthVal;
    for (int i = 1; i <= 12; i++) {
      BigDecimal max = sumValue.multiply(new BigDecimal(1.1));
      BigDecimal min = sumValue.multiply(new BigDecimal(0.9));
      nextMouthVal = new BigDecimal(Math.random()).multiply(max.subtract(min)).add(min);
      BigDecimal maxNpw = sumNwp.multiply(new BigDecimal(1.2));
      BigDecimal minNwp = sumNwp.multiply(new BigDecimal(0.8));
      nextMouthNwpVal = new BigDecimal(Math.random()).multiply(maxNpw.subtract(minNwp)).add(minNwp);
      ForecastPowerThroughoutTheYear forcecastPowerThroughoutTheYear1 = new ForecastPowerThroughoutTheYear();
      forcecastPowerThroughoutTheYear1.setFpValue(nextMouthVal.setScale(2, BigDecimal.ROUND_HALF_UP));
      forcecastPowerThroughoutTheYear1.setGenDate(cal.getTime());
      sumNwp = nextMouthNwpVal;
      forcecastPowerThroughoutTheYear1.setValue(sumNwp.setScale(2, BigDecimal.ROUND_HALF_UP));
      forcecastPowerThroughoutTheYear1.setYearMonth(yearMonth);
      forcecastPowerThroughoutTheYear1.setForecastTime(startTime);
      forecastPowerThroughoutTheYearList.add(forcecastPowerThroughoutTheYear1);
      sumValue = nextMouthVal;
    }


    long time = DateUtil.beginOfMonth(new Date(startTime)).getTime();
    forecastPowerThroughoutTheYearRepository.deleteAllByForecastTimeBetween(time, startTime);
    forecastPowerThroughoutTheYearRepository.saveAll(forecastPowerThroughoutTheYearList);
    return forecastPowerThroughoutTheYearList;
  }


  /**
   * 定时任务
   * 每月一号执行
   */
  @Scheduled(cron = "0 0 1 1 * ?")
  @Transactional(propagation = Propagation.REQUIRED)
  public void ForecastPowerThroughoutTheYearCron() throws BusinessException {
    Date systemDate = new Date();
    Long startTime = systemDate.getTime();

    ElectricField electricField = electricFieldService.get();

    this.ForecastPowerThroughoutTheYear(startTime,electricField);

  }

  /**
   * 根据年月查询
   *
   * @param yearMonth
   * @return
   */
  public List<ForecastPowerThroughoutTheYear> findByYearMonthLike(String yearMonth) {
    return forecastPowerThroughoutTheYearRepository.findByYearMonthLike(yearMonth);
  }
}
