package com.jiayue.ipp.idp.service.impl;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jiayue.ipp.common.data.entity.*;
import com.jiayue.ipp.idp.mapper.PowerStationStatusDataMapper;
import com.jiayue.ipp.idp.service.*;
import org.springframework.stereotype.Service;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.ZoneOffset;
import java.util.*;
import java.util.stream.Collectors;

/**
 * idp_power_station_status_data
 *
 * @author whc
 * @date 2022-03-18 15:49:20
 */
@Service
public class PowerStationStatusDataServiceImpl extends ServiceImpl<PowerStationStatusDataMapper, PowerStationStatusData> implements PowerStationStatusDataService {
    private final ForecastPowerUltraShortTermHisService forecastPowerUltraShortTermHisService;
    private final ForecastPowerUltraShortTermService forecastPowerUltraShortTermService;
    private final ForecastPowerShortTermService forecastPowerShortTermService;
    private final ElectricFieldServiceImpl electricFieldService;
    private final ForecastManufactorService forecastManufactorService;
    private final ForecastPowerShortTermHisService forecastPowerShortTermHisService;

    public PowerStationStatusDataServiceImpl(ForecastPowerShortTermHisService forecastPowerShortTermHisService, ForecastPowerUltraShortTermHisService forecastPowerUltraShortTermHisService, ForecastPowerUltraShortTermService forecastPowerUltraShortTermService, ForecastPowerShortTermService forecastPowerShortTermService, ElectricFieldServiceImpl electricFieldService, ForecastManufactorService forecastManufactorService) {
        this.forecastPowerUltraShortTermHisService = forecastPowerUltraShortTermHisService;
        this.forecastPowerUltraShortTermService = forecastPowerUltraShortTermService;
        this.forecastPowerShortTermService = forecastPowerShortTermService;
        this.electricFieldService = electricFieldService;
        this.forecastManufactorService = forecastManufactorService;
        this.forecastPowerShortTermHisService = forecastPowerShortTermHisService;
    }

    @Override
    public List<PowerStationStatusData> findByStationCodeAndStartTimeAndEndTime(String stationCode, Date startTime, Date endTime) {
        QueryWrapper<PowerStationStatusData> wrapper = new QueryWrapper<>();
        if (stationCode != null && !stationCode.equals("")) {
            wrapper.eq("station_code", stationCode);
        }
        if (startTime != null && !startTime.equals("") && endTime != null && !endTime.equals("")) {
            wrapper.between("time", startTime, endTime);
        }
        return baseMapper.selectList(wrapper);
    }

    public List<ArrayList<String>> timeStamp(Date startTime, Date endTime) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String startDate = sdf.format(startTime);
        String endDate = sdf.format(endTime);
        List<ArrayList<String>> dateList = new ArrayList<>();
        while (startDate.compareTo(endDate) <= 0) {
            List<String> subList = new ArrayList<>();
            subList.add(startDate);
            dateList.add(new ArrayList<>(subList));
            startDate = nextSecond(startDate);
        }
        return dateList;
    }

    public static String nextSecond(String str) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = sdf.parse(str);
        long time = date.getTime() + 1000L * 60 * 15;
        date = new Date(time);
        return sdf.format(date);
    }

    public Map<String, List> getCompositeData(String stationCode, Date startTime, Date endTime, String forecastManufactor, Integer cdqPoint, Integer dqPoint) {
        Long startDateTime = startTime.getTime();
        Long endDateTime = endTime.getTime();
        ElectricField electricField = electricFieldService.findByStationCode(stationCode);
        String station = "";
        String queryForecastManufactor ="";
        if (stationCode != null && !stationCode.equals("")) {
            station = electricField.getName();
        }
        List<ForecastManufactor> forecastManufactorList = forecastManufactorService.list();

        // 页面查询预测厂家条件为空，需要查询场站信息下绑定的所有厂家
        if ("".equals(forecastManufactor)||forecastManufactor==null){
            queryForecastManufactor = electricField.getForecastManufactor();
        }
        else{
            // 查询页面条件选择的厂家
            queryForecastManufactor = forecastManufactor;
        }

        // 封装列表头信息
        List headList = new ArrayList();
        Map<String,String> czmcHeadMap = new HashMap<>();
        czmcHeadMap.put("field", "czmc");
        czmcHeadMap.put("label", "场站名称");
        headList.add(czmcHeadMap);
        Map<String,String> timeHeadMap = new HashMap<>();
        timeHeadMap.put("field", "time");
        timeHeadMap.put("label", "时间");
        headList.add(timeHeadMap);
        Map<String,String> sjglHeadMap = new HashMap<>();
        sjglHeadMap.put("field", "sjgl");
        sjglHeadMap.put("label", "实际功率");
        headList.add(sjglHeadMap);


        String[] fm = queryForecastManufactor.split(",");
        // 按厂家过滤出数据
        Map<String,List> tempDqMap = new HashMap<>();
        Map<String,List> tableDqMap = new HashMap<>();
       if(dqPoint>0){
           // 获取短期数据
           List<ForecastPowerShortTermHis> forecastPowerShortTermHisList = forecastPowerShortTermHisService.findByForecastTimeBetweenAndForecastHowLongAgoAndStationCode(startTime.getTime(), endTime.getTime(),dqPoint,stationCode);


           for (int i=0;i<fm.length;i++){
               int finalI = i;
               List<ForecastPowerShortTermHis> result = forecastPowerShortTermHisList.stream().filter(c -> c.getForecastManufactor().equals(fm[finalI])).collect(Collectors.toList());
               Map<Long, String> dqMap = new HashMap<>();
               for (ForecastPowerShortTermHis forecastPowerShortTermHis : result) {
                   dqMap.put(forecastPowerShortTermHis.getForecastTime().getTime(), forecastPowerShortTermHis.getAbleValue().toString());
               }
               List tempdqList = new ArrayList();
               for (Long tempDateTime = startDateTime; tempDateTime < endDateTime; tempDateTime = tempDateTime + 15 * 60 * 1000) {
                   if (dqMap.get(tempDateTime) != null) {
                       tempdqList.add(dqMap.get(tempDateTime).toString());
                   } else {
                       tempdqList.add(null);
                   }
               }
               String manufactorName = "";
               for (ForecastManufactor forecastManufactor1:forecastManufactorList){
                   if (fm[finalI].equals(forecastManufactor1.getSign())){
                       manufactorName = forecastManufactor1.getName();
                       break;
                   }
               }
               if ("".equals(manufactorName)){
                   manufactorName = fm[finalI];
               }
               tempDqMap.put(manufactorName,tempdqList);
               tableDqMap.put(fm[finalI],tempdqList);
               Map<String,String> dqHeadMap = new HashMap<>();
               dqHeadMap.put("field", fm[finalI]+"DQ");
               dqHeadMap.put("label", manufactorName+"短期");
               headList.add(dqHeadMap);
           }
       }else {
           // 获取短期数据
           List<ForecastPowerShortTerm> forecastPowerShortTermList = forecastPowerShortTermService.findByStationCodeAndStartTimeAndEndTime(stationCode,startTime,endTime);


           for (int i=0;i<fm.length;i++){
               int finalI = i;
               List<ForecastPowerShortTerm> result = forecastPowerShortTermList.stream().filter(c -> c.getForecastManufactor().equals(fm[finalI])).collect(Collectors.toList());
               Map<Long, String> dqMap = new HashMap<>();
               for (ForecastPowerShortTerm forecastPowerShortTerm : result) {
                   dqMap.put(forecastPowerShortTerm.getForecastTime().getTime(), forecastPowerShortTerm.getFpValue().toString());
               }
               List tempdqList = new ArrayList();
               for (Long tempDateTime = startDateTime; tempDateTime < endDateTime; tempDateTime = tempDateTime + 15 * 60 * 1000) {
                   if (dqMap.get(tempDateTime) != null) {
                       tempdqList.add(dqMap.get(tempDateTime).toString());
                   } else {
                       tempdqList.add(null);
                   }
               }
               String manufactorName = "";
               for (ForecastManufactor forecastManufactor1:forecastManufactorList){
                   if (fm[finalI].equals(forecastManufactor1.getSign())){
                       manufactorName = forecastManufactor1.getName();
                       break;
                   }
               }
               if ("".equals(manufactorName)){
                   manufactorName = fm[finalI];
               }
               tempDqMap.put(manufactorName,tempdqList);
               tableDqMap.put(fm[finalI],tempdqList);
               Map<String,String> dqHeadMap = new HashMap<>();
               dqHeadMap.put("field", fm[finalI]+"DQ");
               dqHeadMap.put("label", manufactorName+"短期");
               headList.add(dqHeadMap);
           }
       }

        Map<String,List> tempCdqMap = new HashMap<>();
        Map<String,List> tableCdqMap = new HashMap<>();
        if(cdqPoint>0){
            // 获取超短期数据
            List<ForecastPowerUltraShortTermHis> forecastPowerUltraShortTermHisList = forecastPowerUltraShortTermHisService.findByForecastTimeBetweenAndForecastHowLongAgoAndStationCode(startTime.getTime(), endTime.getTime(), cdqPoint, stationCode);
            // 按厂家过滤出数据
            for (int i=0;i<fm.length;i++){
                int finalI = i;
                List<ForecastPowerUltraShortTermHis> result = forecastPowerUltraShortTermHisList.stream().filter(c -> c.getForecastManufactor().equals(fm[finalI])).collect(Collectors.toList());
                Map<Long, String> cdqMap = new HashMap<>();
                for (ForecastPowerUltraShortTermHis forecastPowerUltraShortTermHis : result) {
                    cdqMap.put(forecastPowerUltraShortTermHis.getForecastTime().getTime(), forecastPowerUltraShortTermHis.getAbleValue().toString());
                }
                List tempcdqList = new ArrayList();
                for (Long tempDateTime = startDateTime; tempDateTime < endDateTime; tempDateTime = tempDateTime + 15 * 60 * 1000) {
                    if (cdqMap.get(tempDateTime) != null) {
                        tempcdqList.add(cdqMap.get(tempDateTime).toString());
                    } else {
                        tempcdqList.add(null);
                    }
                }
                String manufactorName = "";
                for (ForecastManufactor forecastManufactor1:forecastManufactorList){
                    if (fm[finalI].equals(forecastManufactor1.getSign())){
                        manufactorName = forecastManufactor1.getName();
                        break;
                    }
                }
                if ("".equals(manufactorName)){
                    manufactorName = fm[finalI];
                }
                tempCdqMap.put(manufactorName,tempcdqList);
                tableCdqMap.put(fm[finalI],tempcdqList);
                Map<String,String> cdqHeadMap = new HashMap<>();
                cdqHeadMap.put("field", fm[finalI]+"CDQ");
                cdqHeadMap.put("label", manufactorName+"超短期");
                headList.add(cdqHeadMap);
            }
        }
        else{
            // 获取超短期实时数据
            List<ForecastPowerUltraShortTerm> forecastPowerUltraShortTermList = forecastPowerUltraShortTermService.findByStationCodeAndStartTimeAndEndTime(stationCode,startTime, endTime);
            // 按厂家过滤出数据
            for (int i=0;i<fm.length;i++){
                int finalI = i;
                List<ForecastPowerUltraShortTerm> result = forecastPowerUltraShortTermList.stream().filter(c -> c.getForecastManufactor().equals(fm[finalI])).collect(Collectors.toList());
                Map<Long, String> cdqMap = new HashMap<>();
                for (ForecastPowerUltraShortTerm forecastPowerUltraShortTerm : result) {
                    cdqMap.put(forecastPowerUltraShortTerm.getForecastTime().getTime(), forecastPowerUltraShortTerm.getFpValue().toString());
                }
                List tempcdqList = new ArrayList();
                for (Long tempDateTime = startDateTime; tempDateTime < endDateTime; tempDateTime = tempDateTime + 15 * 60 * 1000) {
                    if (cdqMap.get(tempDateTime) != null) {
                        tempcdqList.add(cdqMap.get(tempDateTime).toString());
                    } else {
                        tempcdqList.add(null);
                    }
                }
                String manufactorName = "";
                for (ForecastManufactor forecastManufactor1:forecastManufactorList){
                    if (fm[finalI].equals(forecastManufactor1.getSign())){
                        manufactorName = forecastManufactor1.getName();
                        break;
                    }
                }
                if ("".equals(manufactorName)){
                    manufactorName = fm[finalI];
                }
                tempCdqMap.put(manufactorName,tempcdqList);
                tableCdqMap.put(fm[finalI],tempcdqList);
                Map<String,String> cdqHeadMap = new HashMap<>();
                cdqHeadMap.put("field", fm[finalI]+"CDQ");
                cdqHeadMap.put("label", manufactorName+"超短期");
                headList.add(cdqHeadMap);
            }
        }


        List<String> timeList = new ArrayList<>();
        List<String> sjList = new ArrayList();
        List<Map> dqList = new ArrayList();
        dqList.add(tempDqMap);
        List<Map> cdqList = new ArrayList();
        cdqList.add(tempCdqMap);
        // 获取实际功率
        Map<Long, String> sjMap = new HashMap<>();
        List<PowerStationStatusData> powerStationStatusDataList = findByStationCodeAndStartTimeAndEndTime(stationCode, startTime, endTime);
        for (PowerStationStatusData powerStationStatusData : powerStationStatusDataList) {
            sjMap.put(powerStationStatusData.getTime().toInstant(ZoneOffset.of("+8")).toEpochMilli(), powerStationStatusData.getRealValue().toString());
        }
        List<Map<String,Object>> tableList = new ArrayList();
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        int i=0;
        for (Long tempDateTime = startDateTime; tempDateTime < endDateTime; tempDateTime = tempDateTime + 15 * 60 * 1000) {
            // 封装实际功率list
            if (sjMap.get(tempDateTime) != null) {
                if (Double.parseDouble(sjMap.get(tempDateTime))==-99) {
                    sjList.add(null);
                }
                else{
                    sjList.add(sjMap.get(tempDateTime).toString());
                }
            } else {
                sjList.add(null);
            }
            // 封装时间轴list
            String time = format.format(tempDateTime);
            timeList.add(time);
            // 封装列表的数据
            Map<String,Object> map1 = new HashMap<>();
            map1.put("czmc", station);
            map1.put("time", DateUtil.format(new Date(tempDateTime), "yyyy-MM-dd HH:mm"));
            map1.put("sjgl",sjMap.get(tempDateTime) != null?sjMap.get(tempDateTime).toString():null);
            // 遍历短期数据
            for (Map.Entry<String, List> entry : tableDqMap.entrySet()) {
                List tempdqList = entry.getValue();
                map1.put(entry.getKey()+"DQ",tempdqList.get(i));
            }
            // 遍历超短期数据
            for (Map.Entry<String, List> entry : tableCdqMap.entrySet()) {
                List tempcdqList = entry.getValue();
                map1.put(entry.getKey()+"CDQ",tempcdqList.get(i));
            }

            i++;
            tableList.add(map1);
        }


        Map<String, List> map = new HashMap<>();
        map.put("dq", dqList);
        map.put("cdq", cdqList);
        map.put("sj", sjList);
        map.put("time", timeList);
        map.put("fromHead", headList);
        map.put("tableList", tableList);

        return map;
    }

    @Override
    public List<PowerStationStatusData> findByTimeBetweenAndStationCode(Date pointStarTime, Date pointEndTime, String stationCode) {
        QueryWrapper<PowerStationStatusData> wrapper = new QueryWrapper<>();

        if (stationCode != null && !stationCode.equals("")) {
            wrapper.eq("station_code", stationCode);
        }
        if (pointStarTime != null && pointEndTime != null) {
            wrapper.between("time", pointStarTime, pointEndTime);
        }
        return baseMapper.selectList(wrapper);
    }
}
