package com.cpp.web.controller.regulation;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.cpp.common.core.domain.R;
import com.cpp.common.utils.DateUtils;
import com.cpp.web.domain.accuracy.AccuracyPassRate;
import com.cpp.web.domain.enums.DataSourcesEnum;
import com.cpp.web.domain.enums.ForecastTypeEnum;
import com.cpp.web.domain.regulation.TempShortRegulation;
import com.cpp.web.domain.regulation.TempShortUsual;
import com.cpp.web.domain.regulation.TempShortUsualDetail;
import com.cpp.web.domain.station.ElectricField;
import com.cpp.web.domain.station.ForecastPowerShortTermStation;
import com.cpp.web.domain.station.WeatherStationStatusData;
import com.cpp.web.domain.station.WindTurbineInfo;
import com.cpp.web.dto.TempShortRegulationDto;
import com.cpp.web.service.accuracy.AccuracyPassRateService;
import com.cpp.web.service.regulation.TempShortRegulationService;
import com.cpp.web.service.regulation.TempShortUsualDetailService;
import com.cpp.web.service.regulation.TempShortUsualService;
import com.cpp.web.service.station.ElectricFieldService;
import com.cpp.web.service.station.ForecastPowerShortTermStationService;
import com.cpp.web.utils.DateTimeUtil;
import lombok.RequiredArgsConstructor;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

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


/**
 * 短期调控
 *
 * @author whc
 * @date 2022-03-18 15:49:14
 */
@RestController
@RequiredArgsConstructor
@RequestMapping("/dqRegulationController")
public class DqRegulationController {
    @Autowired
    ForecastPowerShortTermStationService forecastPowerShortTermStationService;
    @Autowired
    AccuracyPassRateService accuracyPassRateService;
    @Autowired
    TempShortRegulationService tempShortRegulationService;
    @Autowired
    ElectricFieldService electricFieldService;
    @Autowired
    TempShortUsualService tempShortUsualService;
    @Autowired
    TempShortUsualDetailService tempShortUsualDetailService;



    @GetMapping("/queryData")
    public R queryData(String stationCode, Long time) {
        int howLongAgo = DateTimeUtil.getDaysBetweenTwoDate(System.currentTimeMillis(),time);
        // 获取要调整的短期那天的最后时间
        long endTime = DateTimeUtil.getDayLastTime(time).getTime();

        // 获取短期上报数据(原始数据)
        Map<String, Object> map = new HashMap<>();
        List<ForecastPowerShortTermStation> forecastPowerShortTermStationList = forecastPowerShortTermStationService.findByForecastTimeBetweenAndForecastHowLongAgoAndStationCode(new Date(time), new Date(endTime), howLongAgo, stationCode);
        if (forecastPowerShortTermStationList.size()>0){
            Map<Long, BigDecimal> ysShortMap = new HashMap<>();
            for (ForecastPowerShortTermStation forecastPowerShortTermStation:forecastPowerShortTermStationList) {
                ysShortMap.putIfAbsent(forecastPowerShortTermStation.getTime().getTime(), forecastPowerShortTermStation.getFpValue());
            }
            // 获取前30天的准确率生成参考值
            Date accuracyEndDate = DateUtil.offsetDay(new Date(), -1);
            Date accuracyStartDate = DateUtil.offsetDay(new Date(), -30);

            List<AccuracyPassRate> accuracyPassRateList = accuracyPassRateService.findByTimeBetweenAndForecastTypeAndDataSourcesAndAgoAndForecastModelAndStationCode(DateTimeUtil.getDayStartTime(accuracyStartDate.getTime()), DateTimeUtil.getDayLastTime(accuracyEndDate.getTime()), ForecastTypeEnum.dq, DataSourcesEnum.E1, howLongAgo, null, stationCode);
            double accuracySum = 0;
            if (accuracyPassRateList.size()>0){
                for (AccuracyPassRate accuracyPassRate:accuracyPassRateList){
                    accuracySum = accuracySum + Double.parseDouble(accuracyPassRate.getAccuracy().replaceAll("%", ""));
                }
                // 计算获取偏差率
                accuracySum = 100 - accuracySum / accuracyPassRateList.size();
            }
            // 获取调控数据
            QueryWrapper<TempShortRegulation> tempShortRegulationQueryWrapper = new QueryWrapper<>();
            tempShortRegulationQueryWrapper.eq("station_code", stationCode);
            tempShortRegulationQueryWrapper.eq("tk_date", DateTimeUtil.getDayStartTime(System.currentTimeMillis()));
            tempShortRegulationQueryWrapper.eq("forecast_date", new Date(time));
            tempShortRegulationQueryWrapper.between("time", new Date(time), new Date(endTime));
            List<TempShortRegulation> tempShortRegulationList = tempShortRegulationService.list(tempShortRegulationQueryWrapper);
            List<TempShortRegulationDto> tempList = new ArrayList<>();
            if (tempShortRegulationList.size()==96){
                for (TempShortRegulation tempShortRegulation:tempShortRegulationList){
                    TempShortRegulationDto tempShortRegulationDto = new TempShortRegulationDto();
                    tempShortRegulationDto.setTime(DateUtils.parseDateToStr("HH:mm",tempShortRegulation.getTime()));
                    tempShortRegulationDto.setForecastDate(tempShortRegulation.getForecastDate());
                    tempShortRegulationDto.setTkDate(tempShortRegulation.getTkDate());
                    tempShortRegulationDto.setYsValue(tempShortRegulation.getYsValue());
                    tempShortRegulationDto.setTkValue(tempShortRegulation.getTkValue());
                    tempShortRegulationDto.setSz(tempShortRegulation.getSz());
                    tempShortRegulationDto.setXs(tempShortRegulation.getXs());
                    tempShortRegulationDto.setStationCode(stationCode);
                    tempList.add(tempShortRegulationDto);
                }
            }
            Map<Long, BigDecimal> tkShortMap = new HashMap<>();
            for (TempShortRegulation tempShortRegulation:tempShortRegulationList) {
                tkShortMap.putIfAbsent(tempShortRegulation.getTime().getTime(), tempShortRegulation.getTkValue());
            }
            // 调控数据
            List<List<Object>> tkDataList = new ArrayList<>();
            // 原始短期数据
            List<BigDecimal> ysList = new ArrayList<>();
            // 参考上限短期
            List<BigDecimal> refUpList = new ArrayList<>();
            // 参考下限短期
            List<BigDecimal> refDownList = new ArrayList<>();
            ElectricField electricField = electricFieldService.findByStationCode(stationCode);
            Long momentTime = 15 * 60 * 1000L;
            for (Long tempTime = time; tempTime <= endTime; tempTime = tempTime + momentTime) {
                List<Object> listAfter = new ArrayList<>();
                listAfter.add(DateUtils.parseDateToStr("HH:mm",new Date(tempTime)));
                if (ysShortMap.get(tempTime)!=null){
                    ysList.add(ysShortMap.get(tempTime));
                    if (accuracySum>0){
                        // 计算出偏差量
                        BigDecimal baseValue = ysShortMap.get(tempTime).multiply(new BigDecimal(accuracySum).multiply(new BigDecimal("0.01"))).setScale(2, BigDecimal.ROUND_HALF_UP);
                        // 在原始数据基础上，生成上下限值。
                        BigDecimal sx = ysShortMap.get(tempTime).add(baseValue).setScale(2, BigDecimal.ROUND_HALF_UP);
                        if (sx.compareTo(electricField.getCapacity())==1){
                            sx = electricField.getCapacity();
                        }
                        BigDecimal xx = ysShortMap.get(tempTime).subtract(baseValue).setScale(2, BigDecimal.ROUND_HALF_UP);
                        if (xx.compareTo(new BigDecimal("0"))==-1){
                            xx = new BigDecimal("0");
                        }
                        refUpList.add(sx);
                        refDownList.add(xx);
                    }

                    if (tempShortRegulationList.isEmpty()){
                        // 使用原始值
                        TempShortRegulationDto tempShortRegulationDto = new TempShortRegulationDto();
                        tempShortRegulationDto.setTime(DateUtils.parseDateToStr("HH:mm",new Date(tempTime)));
                        tempShortRegulationDto.setForecastDate(new Date(time));
                        tempShortRegulationDto.setTkDate(new Date());
                        tempShortRegulationDto.setYsValue(ysShortMap.get(tempTime));
                        tempShortRegulationDto.setTkValue(ysShortMap.get(tempTime));
                        tempShortRegulationDto.setSz(new BigDecimal("0"));
                        tempShortRegulationDto.setXs(new BigDecimal("1"));
                        tempShortRegulationDto.setStationCode(stationCode);
                        tempList.add(tempShortRegulationDto);
                        // 调控曲线使用原始值
                        listAfter.add(ysShortMap.get(tempTime));
                    }
                    else{
                        // 封装调控值
                        listAfter.add(tkShortMap.get(tempTime));
                    }
                }
                else{
                    ysList.add(null);
                    refUpList.add(null);
                    refDownList.add(null);
                    listAfter.add(null);
                }
                tkDataList.add(listAfter);
            }
            // 原始值
            map.put("ysData",ysList);
            // 参考上限
            map.put("refUpData",refUpList);
            // 参考下限
            map.put("refDownData",refDownList);
            // 页面列表
            map.put("tempShortRegulationList",tempList);
            // 页面调控曲线数值
            map.put("tkDataList",tkDataList);


            map.put("electricField",electricField);

            return R.ok(map);
        }
        else{
            String timeStr = DateUtil.format(new Date(time),"yyyy-MM-dd");
            return R.fail("调控日期："+timeStr+"，今日无上报数据！");
        }
    }
    @PostMapping("/updateDqRegulation")
    public R updateDqRegulation(@RequestBody List<TempShortRegulationDto> tempShortRegulationDtoList) {
        // 先删除调控表中已有的数据
        TempShortRegulationDto tempShortRegulationDto = tempShortRegulationDtoList.get(0);
        // 调控的预测日期
        Date forecastDate = tempShortRegulationDto.getForecastDate();
        Date startTime = DateTimeUtil.getDayStartTime(forecastDate.getTime());
        Date endTime = DateTimeUtil.getDayLastTime(forecastDate.getTime());
        QueryWrapper<TempShortRegulation> tempShortRegulationQueryWrapper = new QueryWrapper<>();
        tempShortRegulationQueryWrapper.eq("station_code", tempShortRegulationDto.getStationCode());
        tempShortRegulationQueryWrapper.eq("forecast_date", tempShortRegulationDto.getForecastDate());
        tempShortRegulationQueryWrapper.eq("tk_date", DateTimeUtil.getDayStartTime(System.currentTimeMillis()));
        tempShortRegulationQueryWrapper.between("time", startTime, endTime);
        tempShortRegulationService.remove(tempShortRegulationQueryWrapper);
        // 封装新的调控插入数据
        List<TempShortRegulation> tempShortRegulationList = new ArrayList<>();
        for (TempShortRegulationDto tempShortRegulationDto1 : tempShortRegulationDtoList) {
            TempShortRegulation tempShortRegulation = new TempShortRegulation();
            tempShortRegulation.setStationCode(tempShortRegulationDto1.getStationCode());
            tempShortRegulation.setForecastDate(tempShortRegulationDto1.getForecastDate());
            tempShortRegulation.setTkDate(tempShortRegulationDto1.getTkDate());
            Date time = DateUtil.parse(DateUtil.format(tempShortRegulationDto1.getForecastDate(),"yyyy-MM-dd")+" "+tempShortRegulationDto1.getTime(), "yyyy-MM-dd HH:mm");
            tempShortRegulation.setTime(time);
            tempShortRegulation.setSz(tempShortRegulationDto1.getSz());
            tempShortRegulation.setXs(tempShortRegulationDto1.getXs());
            tempShortRegulation.setTkValue(tempShortRegulationDto1.getTkValue());
            tempShortRegulation.setYsValue(tempShortRegulationDto1.getYsValue());
            tempShortRegulationList.add(tempShortRegulation);
        }
        tempShortRegulationService.saveBatch(tempShortRegulationList);
        return R.ok();
    }

    /**
     * 试算数据
     * @param stationCode
     * @param time
     * @param usualName 常规策略名称
     * @return
     */

    @GetMapping("/trialData")
    public R trialData(String stationCode, Long time,String usualName) {
        // 先获取常规策略
        QueryWrapper<TempShortUsual> tempShortUsualQueryWrapper = new QueryWrapper<>();
        tempShortUsualQueryWrapper.eq("usual_name", usualName);
        TempShortUsual tempShortUsual = tempShortUsualService.getOne(tempShortUsualQueryWrapper);
        QueryWrapper<TempShortUsualDetail> tempShortUsualDetailQueryWrapper = new QueryWrapper<>();
        tempShortUsualDetailQueryWrapper.eq("usual_id", tempShortUsual.getId());
        List<TempShortUsualDetail> tempShortUsualDetailList = tempShortUsualDetailService.list(tempShortUsualDetailQueryWrapper);
        Map<String,TempShortUsualDetail> usualDetailMap = new HashMap<>();
        for (TempShortUsualDetail tempShortUsualDetail:tempShortUsualDetailList){
            usualDetailMap.put(tempShortUsualDetail.getTimePoint(),tempShortUsualDetail);
        }
        int howLongAgo = DateTimeUtil.getDaysBetweenTwoDate(System.currentTimeMillis(),time);
        // 获取要调整的短期那天的最后时间
        long endTime = DateTimeUtil.getDayLastTime(time).getTime();
        // 获取短期上报数据(原始数据)
        List<ForecastPowerShortTermStation> forecastPowerShortTermStationList = forecastPowerShortTermStationService.findByForecastTimeBetweenAndForecastHowLongAgoAndStationCode(new Date(time), new Date(endTime), howLongAgo, stationCode);
        Map<Long, BigDecimal> ysShortMap = new HashMap<>();
        for (ForecastPowerShortTermStation forecastPowerShortTermStation:forecastPowerShortTermStationList) {
            ysShortMap.putIfAbsent(forecastPowerShortTermStation.getTime().getTime(), forecastPowerShortTermStation.getFpValue());
        }
        Long momentTime = 15 * 60 * 1000L;
        List<TempShortRegulationDto> trialList = new ArrayList<>();
        for (Long tempTime = time; tempTime <= endTime; tempTime = tempTime + momentTime) {
            String timeHHmm = DateUtils.parseDateToStr("HH:mm",new Date(tempTime));
            TempShortRegulationDto tempShortRegulationDto = new TempShortRegulationDto();
            tempShortRegulationDto.setTime(timeHHmm);
            tempShortRegulationDto.setForecastDate(new Date(time));
            tempShortRegulationDto.setTkDate(new Date());
            tempShortRegulationDto.setYsValue(ysShortMap.get(tempTime));
            TempShortUsualDetail tempShortUsualDetail = usualDetailMap.get(timeHHmm);
            tempShortRegulationDto.setSz(tempShortUsualDetail.getSz());
            tempShortRegulationDto.setXs(tempShortUsualDetail.getXs());
            // 计算调控值，调控值=原始值*系数+数值
            BigDecimal tkValue = ysShortMap.get(tempTime).multiply(tempShortUsualDetail.getXs()).add(tempShortUsualDetail.getSz()).setScale(2, BigDecimal.ROUND_HALF_UP);
            tempShortRegulationDto.setTkValue(tkValue);
            tempShortRegulationDto.setStationCode(stationCode);
            trialList.add(tempShortRegulationDto);
        }
        return R.ok(trialList);
    }
}
