package com.gyee.generation.service;

import com.gyee.common.contant.ContantXk;
import com.gyee.common.model.PointData;
import com.gyee.generation.config.feign.RemoteServiceBuilder;
import com.gyee.generation.config.feign.TsDoubleData;
import com.gyee.generation.init.CacheContext;
import com.gyee.generation.model.auto.*;
import com.gyee.generation.model.vo.StatData;
import com.gyee.generation.model.vo.WpType;
import com.gyee.generation.service.auto.IProEconWtPowerCurveFittingService;
import com.gyee.generation.service.auto.ITurbineInfoMinService;
import com.gyee.generation.util.DateUtils;
import com.gyee.generation.util.StringUtils;
import com.gyee.generation.util.realtimesource.IEdosUtil;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class CoefficientService {

    @Resource
    private ITurbineInfoMinService turbineInfoMinService;

    public Map<String, Map<String, Double>> coefficient(String wtId, Date currentDate) throws Exception {



            Date beginDate = DateUtils.addDays(currentDate, -1);


            Calendar c = Calendar.getInstance();
            c.setTime(beginDate);

            c.set(Calendar.DAY_OF_MONTH, 1);
            Date monthbeginDate = c.getTime();
            c.set(Calendar.MONTH, 0);
            Date yearbeginDate = c.getTime();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String beginDateString = sdf.format(beginDate);
            String monthbeginDateString = sdf.format(monthbeginDate);
            String yearbeginDateString = sdf.format(yearbeginDate);

            Date endDate = currentDate;
            String endDateString = sdf.format(endDate);

            Map<String, Map<String, Double>> resultmap = new HashMap<>();

            ProBasicEquipment wt = CacheContext.wtmap.get(wtId);

//        if (wtId.equals("NX_FGS_HA_F_WT_0027_EQ")) {
            //****************************************年功率一致性统计********************************************************************/
            List<ProEconActivePowerData> yearList;

            List<ProEconActivePowerData> queryYear = new ArrayList<>();

            List<TurbineInfoMin> infoMinsy = turbineInfoMinService.selectByTurbineId(wt.getId(), yearbeginDateString, beginDateString);
            // 使用 Stream API 按小时分组并计算平均风速和累加pjgl
            Map<String, List<TurbineInfoMin>> groupedByHoury = infoMinsy.stream()
                    .collect(Collectors.groupingBy(info -> info.getRecordDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH"))));

            // 计算每小时的平均pjfs和累加pjgl
            for (Map.Entry<String, List<TurbineInfoMin>> entry : groupedByHoury.entrySet()) {
                String hour = entry.getKey();
                List<TurbineInfoMin> hourData = entry.getValue();

                // 计算每小时的平均风速 (pjfs) 和 累加pjgl
                double avgPjfs = hourData.stream()
                        .mapToDouble(TurbineInfoMin::getPjfs)  // 假设有getPjfs方法
                        .average()
                        .orElse(0);

                double totalPjgl = hourData.stream()
                        .mapToDouble(TurbineInfoMin::getPjgl)  // 假设有getPjgl方法
                        .sum();

                ProEconActivePowerData po1 = new ProEconActivePowerData();
                po1.setWindturbineId(wt.getId());
                po1.setModelId(wt.getModelId());
                po1.setWindpowerstationId(wt.getWindpowerstationId());
                po1.setFrequency(groupedByHoury.size());
                po1.setSpeed(StringUtils.round(avgPjfs, 2));
                po1.setPower(StringUtils.round(totalPjgl, 2));
                queryYear.add(po1);
            }

            yearList = calCoefficient(queryYear, wt);

            //****************************************月功率一致性统计********************************************************************/

            List<ProEconActivePowerData> monthList;
            List<ProEconActivePowerData> queryMonth = new ArrayList<>();

            List<TurbineInfoMin> infoMins = turbineInfoMinService.selectByTurbineId(wt.getId(), monthbeginDateString, beginDateString);
            // 使用 Stream API 按小时分组并计算平均风速和累加pjgl
            Map<String, List<TurbineInfoMin>> groupedByHour = infoMins.stream()
                    .collect(Collectors.groupingBy(info -> info.getRecordDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH"))));

            // 计算每小时的平均pjfs和累加pjgl
            for (Map.Entry<String, List<TurbineInfoMin>> entry : groupedByHour.entrySet()) {
                String hour = entry.getKey();
                List<TurbineInfoMin> hourData = entry.getValue();

                // 计算每小时的平均风速 (pjfs) 和 累加pjgl
                double avgPjfs = hourData.stream()
                        .mapToDouble(TurbineInfoMin::getPjfs)  // 假设有getPjfs方法
                        .average()
                        .orElse(0);

                double totalPjgl = hourData.stream()
                        .mapToDouble(TurbineInfoMin::getPjgl)  // 假设有getPjgl方法
                        .sum();

                ProEconActivePowerData po = new ProEconActivePowerData();
                po.setWindturbineId(wt.getId());
                po.setModelId(wt.getModelId());
                po.setWindpowerstationId(wt.getWindpowerstationId());
                po.setFrequency(groupedByHour.size());
                po.setSpeed(StringUtils.round(avgPjfs, 2));
                po.setPower(StringUtils.round(totalPjgl, 2));
                queryMonth.add(po);
            }


            monthList = calCoefficient(queryMonth, wt);


            //*****************************************日功率一致性统计********************************************************************/


            List<ProEconActivePowerData> dayList;


            List<ProEconActivePowerData> queryDay = new ArrayList<>();

            List<TurbineInfoMin> dayinfoMins = turbineInfoMinService.selectByTurbineId(wt.getId(), beginDateString, endDateString);
            // 使用 Stream API 按小时分组并计算平均风速和累加pjgl
            Map<String, List<TurbineInfoMin>> daygroupedByHour = dayinfoMins.stream()
                    .collect(Collectors.groupingBy(info -> info.getRecordDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH"))));

            // 计算每小时的平均pjfs和累加pjgl
            for (Map.Entry<String, List<TurbineInfoMin>> entry : daygroupedByHour.entrySet()) {
                String hour = entry.getKey();
                List<TurbineInfoMin> hourData = entry.getValue();

                // 计算每小时的平均风速 (pjfs) 和 累加pjgl
                double avgPjfs = hourData.stream()
                        .mapToDouble(TurbineInfoMin::getPjfs)  // 假设有getPjfs方法
                        .average()
                        .orElse(0);

                double totalPjgl = hourData.stream()
                        .mapToDouble(TurbineInfoMin::getPjgl)  // 假设有getPjgl方法
                        .sum();

                ProEconActivePowerData po = new ProEconActivePowerData();
                po.setWindturbineId(wt.getId());
                po.setModelId(wt.getModelId());
                po.setWindpowerstationId(wt.getWindpowerstationId());
                po.setFrequency(groupedByHour.size());
                po.setSpeed(StringUtils.round(avgPjfs, 2));
                po.setPower(StringUtils.round(totalPjgl, 2));
                queryDay.add(po);
            }
            dayList = calCoefficient(queryDay, wt);


            Double resultYear = coefficient(yearList, currentDate, wt.getId());
            Double resultMonth = coefficient(monthList, currentDate, wt.getId());
            Double resultDay = coefficient(dayList, currentDate, wt.getId());

            Map<String, Double> tempmap = new HashMap<>();
            tempmap.put("year", resultYear);
            tempmap.put("month", resultMonth);
            tempmap.put("day", resultDay);
            resultmap.put(wt.getId(), tempmap);
//        }
            return resultmap;
    }


    private List<ProEconActivePowerData> calCoefficient(List<ProEconActivePowerData> query, ProBasicEquipment wt) {


        Map<Double, List<ProEconActivePowerData>> apdataYearMap = query.stream().collect(Collectors.groupingBy(ProEconActivePowerData::getSpeed));


        Map<Double, Double> speedAndPowerYearMap = new HashMap<>();
        apdataYearMap.forEach((key, value) -> {
            DoubleSummaryStatistics summaryStatistics = value.stream().mapToDouble(ProEconActivePowerData::getPower).summaryStatistics();
            speedAndPowerYearMap.put(key, summaryStatistics.getAverage());
        });

        List<ProEconActivePowerData> yearList = new ArrayList<>();


        speedAndPowerYearMap.forEach((key, value) -> {

            ProEconActivePowerData activepowerdata = new ProEconActivePowerData();
            activepowerdata.setWindturbineId(wt.getId());
            activepowerdata.setSpeed(key);
            activepowerdata.setPower(value);
            activepowerdata.setFrequency(1);
            activepowerdata.setModelId(wt.getModelId());

            yearList.add(activepowerdata);
        });

        return yearList;

    }


    //功率一致性系数
    private Double coefficient(List<ProEconActivePowerData> dataList, Date currentDate, String windturbineId) {
        double result = 0.0;
        double count = 0.0;

        if (dataList != null && dataList.size() != 0) {


            Calendar c = Calendar.getInstance();
            c.setTime(currentDate);

            //            QueryWrapper<ProEconWtPowerCurveFitting> queryWrapper = new QueryWrapper<>();
            //            queryWrapper.eq("windturbine_id",windturbineId);
            //            powerList = proEconWtPowerCurveFittingService.list(queryWrapper);


            Map<Double, ProEconWtPowerCurveFitting> curveFittingPowerMap = null;
            if (CacheContext.curveFittingPowerMap.containsKey(windturbineId)) {
                curveFittingPowerMap = CacheContext.curveFittingPowerMap.get(windturbineId);

            }

            for (ProEconActivePowerData data : dataList) {
                Double p1 = data.getPower();
                Double speed = data.getSpeed();
                //                if (speed < 3 || speed > 25) {
                //                    continue;
                //                }

                if (CacheContext.wtmap.containsKey(windturbineId)) {
                    ProBasicEquipment wt = CacheContext.wtmap.get(windturbineId);

                    if (wt.getWindpowerstationId().contains(WpType.GDC.id)) {
                        speed /= 100;
                        speed = StringUtils.round(speed, 2);
                        speed *= 100;

                        speed = StringUtils.round(speed, 2);
                    } else {
                        speed = StringUtils.round(speed, 2);
                    }
                }


                if (CacheContext.theoreticalPowerMap.containsKey(data.getModelId())) {
                    if (CacheContext.theoreticalPowerMap.get(data.getModelId()).size() > 0) {
                        if (CacheContext.theoreticalPowerMap.get(data.getModelId()).containsKey(speed)) {
                            Double p = CacheContext.theoreticalPowerMap.get(data.getModelId()).get(speed).getEnsurePower();


                            if (p != 0) {
                                for (int i = 0; i < data.getFrequency(); i++) {
                                    result += Math.abs((p - p1) / p);
                                    count += 1;
                                }
                            }
                        }
                    } else {
                        if (null != curveFittingPowerMap && curveFittingPowerMap.containsKey(speed)) {
                            double optimalPower = curveFittingPowerMap.get(speed).getOptimalPower();

                            if (optimalPower != 0) {
                                for (int i = 0; i < data.getFrequency(); i++) {
                                    result += Math.abs((optimalPower - p1) / optimalPower);
                                    count += 1;
                                }
                            }

                        } else {


                            DoubleSummaryStatistics summaryStatistics = curveFittingPowerMap.entrySet()
                                    .stream()
                                    .collect(Collectors.summarizingDouble(Map.Entry::getKey));
                            double max = summaryStatistics.getMax();
                            if (speed > max) {

                                double actualPower = curveFittingPowerMap.get(speed).getActualPower();

                                if (actualPower != 0.0) {

                                    for (int i = 0; i < data.getFrequency(); i++) {
                                        result += Math.abs((actualPower - p1) / actualPower);
                                        count += 1;
                                    }
                                }
                            }

                        }
                    }
                }

            }
            if (count != 0)
                result = result / count * 100;
            else
                result = 100.0;
        }

        return result;

    }
}


