package com.gyee.runeconomy.service.EarlyWarning;

import com.gyee.common.util.DoubleUtils;
import com.gyee.runeconomy.init.CacheContext;
import com.gyee.runeconomy.model.auto.ProBasicEquipment;
import com.gyee.runeconomy.model.auto.ProEconEquipmentmodel;
import com.gyee.runeconomy.model.auto.TurbineInfoDay;
import com.gyee.runeconomy.model.vo.IndicatorData;
import com.gyee.runeconomy.service.auto.ITurbineInfoDayService;
import com.gyee.runeconomy.util.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.time.LocalDate;
import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class ReportService {

    @Autowired
    private ITurbineInfoDayService turbineInfoDayService;

    public Map Electricity(String wtid, String time) throws Exception {

        //查询时间-开始结束
        String[] timeRange = DateUtils.generateTimeRange(time);

        //去年同期时间
        String qntq = DateUtils.subtractOneYear(time);
        String[] qntime = DateUtils.generateTimeRange(qntq);

        //月天数
        int daysInMonth = DateUtils.getDaysInMonth(timeRange);
        int qnInMonth = DateUtils.getDaysInMonth(qntime);

        System.out.println("开始时间: " + timeRange[0]);
        System.out.println("结束时间: " + timeRange[1]);

        Map<String, Object> map = new HashMap<>();

        List<ProBasicEquipment> collect = CacheContext.wtls.stream()
                .filter(wt -> wtid.equals(wt.getId())).collect(Collectors.toList());
        //获取单机设备容量
        List<ProEconEquipmentmodel> rl = CacheContext.equipmentmodels.stream()
                .filter(mo -> collect.get(0).getModelId().equals(mo.getId())).collect(Collectors.toList());

        double sbrl = 1;
        if (rl.size() > 0) {
            sbrl = rl.get(0).getPowerProduction();
        }
        List<TurbineInfoDay> turbineList = turbineInfoDayService.getTurbineList(wtid, timeRange[0], timeRange[1]);
        List<TurbineInfoDay> tqturbineList = turbineInfoDayService.getTurbineList(wtid, qntime[0], qntime[1]);

        List<IndicatorData> result = new ArrayList<>();


        // 计算值
        double currentPower = sumRounded(turbineList, t -> t.getRfdl());
        double lastYearPower = sumRounded(tqturbineList, t -> t.getRfdl());
        double currentTheoryPower = sumRounded(turbineList, t -> t.getLlfdl());
        double lastYearTheoryPower = sumRounded(tqturbineList, t -> t.getLlfdl());
        double currentWindSpeed = averageRounded(turbineList, t -> t.getPjfs());
        double lastYearWindSpeed = averageRounded(tqturbineList, t -> t.getPjfs());
        double currentUtilization = DoubleUtils.getRoundingNum(currentPower / sbrl, 0);
        double lastYearUtilization = DoubleUtils.getRoundingNum(lastYearPower / sbrl, 0);
        int jhyxsj = daysInMonth * 24;
        int tqjhyxsj = qnInMonth * 24;
        double yxsj = sumRounded(turbineList, t -> t.getYxMin());
        double tqyxsj = sumRounded(tqturbineList, t -> t.getYxMin());
        double currentEquipmentUtilization = (yxsj / jhyxsj * 100);
        currentEquipmentUtilization = new BigDecimal(currentEquipmentUtilization).setScale(2, RoundingMode.HALF_UP).doubleValue();
        double lastYearEquipmentUtilization = (tqyxsj / tqjhyxsj * 100);
        lastYearEquipmentUtilization = new BigDecimal(lastYearEquipmentUtilization).setScale(2, RoundingMode.HALF_UP).doubleValue();
        double jxsj = sumRounded(turbineList, t -> t.getJxMin()); // 假设正确字段
        double tqjxsj = sumRounded(tqturbineList, t -> t.getJxMin());
        double currentEfficiencyCoefficient = (yxsj + jxsj) / jhyxsj * 100;
        currentEfficiencyCoefficient = new BigDecimal(currentEfficiencyCoefficient).setScale(2, RoundingMode.HALF_UP).doubleValue();
        double lastYearEfficiencyCoefficient = (tqyxsj + tqjxsj) / tqjhyxsj * 100;
        lastYearEfficiencyCoefficient = new BigDecimal(lastYearEfficiencyCoefficient).setScale(2, RoundingMode.HALF_UP).doubleValue();
        double currentSmallWindSpeed = averageRounded(turbineList, t -> t.getXfqrfs());
        double lastYearSmallWindSpeed = averageRounded(tqturbineList, t -> t.getXfqrfs());
        double currentRunningWindHours = sumRounded(turbineList, t -> t.getYxfss());
        double lastYearRunningWindHours = sumRounded(tqturbineList, t -> t.getYxfss());
        double currentFaultLossPower = sumRounded(turbineList, t -> t.getGzss());
        double lastYearFaultLossPower = sumRounded(tqturbineList, t -> t.getGzss());
        double currentDispatchLossPower = sumRounded(turbineList, t -> t.getXdss());
        currentDispatchLossPower = new BigDecimal(currentDispatchLossPower).setScale(2, RoundingMode.HALF_UP).doubleValue();
        double lastYearDispatchLossPower = sumRounded(tqturbineList, t -> t.getXdss());
        lastYearDispatchLossPower = new BigDecimal(lastYearDispatchLossPower).setScale(2, RoundingMode.HALF_UP).doubleValue();
        double currentPlannedMaintenanceLossPower = sumRounded(turbineList, t -> t.getJhjxss());
        currentPlannedMaintenanceLossPower = new BigDecimal(currentPlannedMaintenanceLossPower).setScale(2, RoundingMode.HALF_UP).doubleValue();
        double lastYearPlannedMaintenanceLossPower = sumRounded(tqturbineList, t -> t.getJhjxss());
        lastYearPlannedMaintenanceLossPower = new BigDecimal(lastYearPlannedMaintenanceLossPower).setScale(2, RoundingMode.HALF_UP).doubleValue();
        double currentPerformanceLossPower = sumRounded(turbineList, t -> t.getXnss());
        currentPerformanceLossPower = new BigDecimal(currentPerformanceLossPower).setScale(2, RoundingMode.HALF_UP).doubleValue();
        double lastYearPerformanceLossPower = sumRounded(tqturbineList, t -> t.getXnss());
        lastYearPerformanceLossPower = new BigDecimal(lastYearPerformanceLossPower).setScale(2, RoundingMode.HALF_UP).doubleValue();
        double currentFaultDowntime = sumRounded(turbineList, t -> t.getGzMin());
        double lastYearFaultDowntime = sumRounded(tqturbineList, t -> t.getGzMin());
        double currentMaintenanceDowntime = jxsj;
        double lastYearMaintenanceDowntime = tqjxsj;
        double currentGridConnectionTime = yxsj;
        double lastYearGridConnectionTime = tqyxsj;
        double currentStandbyTime = sumRounded(turbineList, t -> t.getDjMin());
        double lastYearStandbyTime = sumRounded(tqturbineList, t -> t.getDjMin());
        double currentCommFailureTime = sumRounded(turbineList, t -> t.getTjMin());
        double lastYearCommFailureTime = sumRounded(tqturbineList, t -> t.getTjMin());
        double currentCalmWindFrequency = sumRounded(turbineList, t -> t.getJfpl());
        double lastYearCalmWindFrequency = sumRounded(tqturbineList, t -> t.getJfpl());

        // 使用方法来简化添加数据
        result.add(createIndicatorData("实际发电量", currentPower, lastYearPower));
        result.add(createIndicatorData("理论发电量", currentTheoryPower, lastYearTheoryPower));
        result.add(createIndicatorData("平均风速", currentWindSpeed, lastYearWindSpeed));
        result.add(createIndicatorData("利用小时", currentUtilization, lastYearUtilization));
        result.add(createIndicatorData("设备可利用率", currentEquipmentUtilization, lastYearEquipmentUtilization));
        result.add(createIndicatorData("等效可用系数", currentEfficiencyCoefficient, lastYearEfficiencyCoefficient));
        result.add(createIndicatorData("小风切入风速", currentSmallWindSpeed, lastYearSmallWindSpeed));
//        result.add(createIndicatorData("小风切入合格率", currentSmallWindRate, lastYearSmallWindRate));
        result.add(createIndicatorData("有效风时数", currentRunningWindHours, lastYearRunningWindHours));
        result.add(createIndicatorData("故障损失电量", currentFaultLossPower, lastYearFaultLossPower));
        result.add(createIndicatorData("调度限电损失电量", currentDispatchLossPower, lastYearDispatchLossPower));
        result.add(createIndicatorData("计划检修损失电量", currentPlannedMaintenanceLossPower, lastYearPlannedMaintenanceLossPower));
        result.add(createIndicatorData("性能未达标损失电量", currentPerformanceLossPower, lastYearPerformanceLossPower));
        result.add(createIndicatorData("故障停运时间", currentFaultDowntime, lastYearFaultDowntime));
        result.add(createIndicatorData("检修停运时间", currentMaintenanceDowntime, lastYearMaintenanceDowntime));
        result.add(createIndicatorData("并网时间", currentGridConnectionTime, lastYearGridConnectionTime));
        result.add(createIndicatorData("待机时间", currentStandbyTime, lastYearStandbyTime));
        result.add(createIndicatorData("通讯中断时间", currentCommFailureTime, lastYearCommFailureTime));
        result.add(createIndicatorData("静风频率", currentCalmWindFrequency, lastYearCalmWindFrequency));
        map.put("lb", result);

        double fdlzzl = DoubleUtils.getRoundingNum(calculateGrowthRate(currentPower, lastYearPower),2);//发电量增长率
        double ssdllj = DoubleUtils.getRoundingNum(currentFaultLossPower + currentDispatchLossPower + currentPlannedMaintenanceLossPower + currentPerformanceLossPower,2); //损失电量合计
        double tqssdllj = DoubleUtils.getRoundingNum(lastYearFaultLossPower + lastYearDispatchLossPower + lastYearPlannedMaintenanceLossPower + lastYearPerformanceLossPower,2);//同期损失电量合计
        double ssdlzzl = DoubleUtils.getRoundingNum(calculateGrowthRate(ssdllj, tqssdllj),2);
        double dlxc = DoubleUtils.getRoundingNum(currentPower - currentTheoryPower, 2);
        String wz1 = "本月" + collect.get(0).getNemCode() + "风机设备利用小时数" + currentUtilization + "小时、同比" + lastYearUtilization + "小时，" +
                "设备可利用率" + currentEquipmentUtilization + "%、同比" + lastYearEquipmentUtilization + "%，等效可用系数" + currentEfficiencyCoefficient + "%、同比" + lastYearEfficiencyCoefficient + "%，" +
                "静风频率达到" + currentCalmWindFrequency + "%、同比" + lastYearCalmWindFrequency + "%。";
        String wz2 = collect.get(0).getNemCode() + "风机" + time + "月平均风速" + currentWindSpeed + "m/s、同比" + lastYearWindSpeed + "m/s，小风平均切入风速" + currentSmallWindSpeed + "m/s、同比" + lastYearSmallWindSpeed + "m/，" +
                "有效风时数" + currentRunningWindHours + "小时、同比" + lastYearRunningWindHours + "小时，实际发电电量" + currentPower + "万kmh、同比" + lastYearPower + "万kwh，同比增长率" + fdlzzl + "%，" +
                "各项损失电量累计" + ssdllj + "万kmh、同比" + tqssdllj + "万kmh，同比增长率" + ssdlzzl + "%，" +
                "理论发电量" + currentTheoryPower + "万kwh，实际发电量与理论发电量相差" + dlxc + "万kwh。";
        map.put("wz1", wz1);
        map.put("wz2", wz2);
        turbineList.sort(Comparator.comparing(TurbineInfoDay::getRecordDate));
        map.put("tb", turbineList);

        return map;
    }

    // 计算增长率
    private double calculateGrowthRate(double current, double lastYear) {
        if (lastYear == 0) {
            return 0; // 避免除以0
        }
        return (current - lastYear) / lastYear;
    }

    // 定义一个方法来创建 IndicatorData
    private IndicatorData createIndicatorData(String name, double currentValue, double lastYearValue) {
        DecimalFormat df = new DecimalFormat("0.00%");
        return new IndicatorData(
                name,
                currentValue,
                lastYearValue,
                df.format(calculateGrowthRate(currentValue, lastYearValue))
        );
    }

    // 定义辅助方法
    private double sumRounded(List<TurbineInfoDay> list, Function<TurbineInfoDay, Double> getter) {
        BigDecimal sum = BigDecimal.ZERO;
        for (TurbineInfoDay t : list) {
            Double value = getter.apply(t);
            BigDecimal bdValue = value == null ? BigDecimal.ZERO : new BigDecimal(value).setScale(2, RoundingMode.HALF_UP);
            sum = sum.add(bdValue);
        }
        return sum.doubleValue();
    }

    private double averageRounded(List<TurbineInfoDay> list, Function<TurbineInfoDay, Double> getter) {
        if (list.isEmpty()) {
            return 0.0;
        }
        BigDecimal total = BigDecimal.ZERO;
        int count = 0;
        for (TurbineInfoDay t : list) {
            Double value = getter.apply(t);
            if (value != null) {
                total = total.add(new BigDecimal(value));
                count++;
            }
        }
        BigDecimal avg = total.divide(new BigDecimal(count), 2, RoundingMode.HALF_UP);
        return avg.doubleValue();
    }
}
