package com.jiayue.ipfcst.integration.service;


import cn.hutool.core.collection.CollectionUtil;
import com.jiayue.ipfcst.common.core.exception.BusinessException;
import com.jiayue.ipfcst.common.core.integration.constant.StatusConstant;
import com.jiayue.ipfcst.common.data.entity.*;
import com.jiayue.ipfcst.common.data.entity.integration.InForecastPowerShortTerm;
import com.jiayue.ipfcst.common.data.entity.integration.InForecastPowerShortTermHis;
import com.jiayue.ipfcst.common.data.repository.AccuracyPassRateRepository;
import com.jiayue.ipfcst.common.data.repository.ForecastPowerShortTermHisRepository;
import com.jiayue.ipfcst.common.data.repository.InForecastPowerShortTermHisRepository;
import com.jiayue.ipfcst.common.data.service.BaseService;
import com.jiayue.ipfcst.service.AccuracyPassRateService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.Predicate;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class IntegrationService extends BaseService {


  @Autowired
  InForecastPowerShortTermHisRepository inForecastPowerShortTermHisRepository;
  @Autowired
  ForecastPowerShortTermHisRepository forecastPowerShortTermHisRepository;
  @Autowired
  AccuracyPassRateService accuracyPassRateService;
  @Autowired
  AccuracyPassRateRepository accuracyPassRateRepository;

  /**
   * 图表
   *
   * @param startTime 开始时间
   * @param endTime   结束时间
   * @param ago       预测间隔
   * @return
   */
  @Transactional(propagation = Propagation.REQUIRED, readOnly = true)
  public Map<String, Object> draw(Long startTime, Long endTime, Integer ago) {

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    List<Float> forecast = new ArrayList<>();
    List<Float> iforecast = new ArrayList<>();
    List<String> times = new ArrayList<>();
    Map<String, Object> map = new HashMap<>();
    long timeStep = 900000L;
    if (startTime % timeStep != 0) {
      startTime = startTime - (startTime % timeStep) + timeStep;
    }
    List<InForecastPowerShortTermHis> ilist = new ArrayList<>();
    List<ForecastPowerShortTermHis> list = new ArrayList<>();
    list = forecastPowerShortTermHisRepository.findByForecastTimeBetweenAndForecastHowLongAgo(startTime, endTime, ago);
    ilist = inForecastPowerShortTermHisRepository.findByForecastTimeBetweenAndForecastHowLongAgo(startTime, endTime, ago);

    for (long i = startTime; i < endTime; i = i + timeStep) {
      long finalI = i;
      List<ForecastPowerShortTermHis> filterf = list.stream().filter(f -> f.getForecastTime() == finalI).collect(Collectors.toList());
      List<InForecastPowerShortTermHis> filterif = ilist.stream().filter(f -> f.getForecastTime() == finalI).collect(Collectors.toList());

      if (CollectionUtil.isNotEmpty(filterf)) {
        forecast.add(filterf.get(0).getAbleValue().floatValue());
      }

      if (CollectionUtil.isNotEmpty(filterif)) {
        iforecast.add(filterif.get(0).getFpValue().floatValue());
      }

      String timeFormat = sdf.format(new Date(finalI));
      times.add(timeFormat);
    }

    map.put("forecast", forecast);
    map.put("iforecast", iforecast);
    map.put("times", times);

    return map;
  }


  /**
   * 分页查询
   *
   * @param startTime
   * @param endTime
   * @param page
   * @param size
   * @param sortOrder
   * @return
   */
  @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
  public Map<String, Object> findByTimeBetweenAndNoForPaging(Long startTime, Long endTime,
                                                             Integer page, Integer size,
                                                             String sortOrder) {


    Map<String, Object> map = new HashMap<>();
    Sort sort = Sort.by(Sort.Direction.DESC, "time");
    if (sortOrder.contains("asc")) {
      sort = Sort.by(Sort.Direction.ASC, "time");
    }
    Specification<AccuracyPassRate> specification = this.specificationFindByTime(startTime, endTime, StatusConstant.INTEGRATION_SIGN);
    Pageable pageable = PageRequest.of(page - 1, size, sort);
    Page AccuracyPassRates = accuracyPassRateRepository.findAll(specification, pageable);
    List<AccuracyPassRate> datas = new ArrayList<>();

    datas = AccuracyPassRates.getContent();

    List<Map<String, Object>> extracted = extracted(datas);
    map.put("content", extracted);
    map.put("count", AccuracyPassRates.getTotalElements());
    return map;


  }


  /**
   * 查询条件 yh
   *
   * @param startTime 开始时间
   * @param endTime   结束时间
   * @return 过滤条件
   */
  Specification<AccuracyPassRate> specificationFindByTime(final Long startTime, final Long endTime, final String backupA) {
    return (Specification<AccuracyPassRate>) (root, criteriaQuery, cb) -> {


      List<Predicate> predicates = new ArrayList<>();
      if (startTime != null) {
        //大于或等于传入时间
        predicates.add(cb.greaterThanOrEqualTo(root.get("time").as(Long.class), startTime));
      }
      if (endTime != null) {
        //小于传入时间
        predicates.add(cb.lessThan(root.get("time").as(Long.class), endTime));
      }

      predicates.add(cb.equal(root.get("backupA").as(String.class), backupA));
      //添加排序的功能
      return cb.and(predicates.toArray(new Predicate[predicates.size()]));

    };
  }

  /**
   * 数据转换
   *
   * @param datas
   * @return
   */
  public List<Map<String, Object>> extracted(List<AccuracyPassRate> datas) {
    List<Map<String, Object>> resultData = new ArrayList<>();

    List<AccuracyPassRate> ilist = datas.stream().filter(a -> a.getBackupA() != null).collect(Collectors.toList());
    if (CollectionUtil.isNotEmpty(ilist)) {
      List<AccuracyPassRate> list = accuracyPassRateRepository.findByTimeBetween(datas.get(0).getTime(), datas.get(datas.size() - 1).getTime());
      SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
      for (AccuracyPassRate a : ilist) {
        Map<String, Object> acc = new HashMap<>();
        acc.put("time", sdf.format(a.getTime()));
        acc.put("acci", a.getShortTermAccuracy());
        acc.put("pai", a.getShortTermPassRate());
        Long time = a.getTime();
        List<AccuracyPassRate> filter = list.stream().filter(i -> i.getTime() == time).collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(filter)) {
          acc.put("acc", filter.get(0).getShortTermAccuracy());
          acc.put("pa", filter.get(0).getShortTermPassRate());
        } else {
          acc.put("acc", null);
          acc.put("pa", null);
        }
        resultData.add(acc);
      }
    }
    return resultData;
  }

  @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
  public String isMenu() {
    return super.getSysParameter("INTEGRATION_MENU", "no");
  }

}
