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.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 = turbineList.stream()
                .mapToDouble(t -> t.getRfdl() == null ? 0 : Math.round(t.getRfdl().doubleValue() * 100.0) / 100.0)
                .sum(); // 本月实际发电量
        double lastYearPower = tqturbineList.stream()
                .mapToDouble(t -> t.getRfdl() == null ? 0 : Math.round(t.getRfdl().doubleValue() * 100.0) / 100.0)
                .sum(); // 去年同期实际发电量


        double currentTheoryPower = turbineList.stream()
                .mapToDouble(t -> t.getLlfdl() == null ? 0 : Math.round(t.getLlfdl().doubleValue() * 100.0) / 100.0)
                .sum(); // 本月理论发电量
        double lastYearTheoryPower = tqturbineList.stream()
                .mapToDouble(t -> t.getLlfdl() == null ? 0 : Math.round(t.getLlfdl().doubleValue() * 100.0) / 100.0)
                .sum(); // 去年同期理论发电量


        double currentWindSpeed = new BigDecimal(
                turbineList.stream()
                        .mapToDouble(t -> t.getPjfs() == null ? 0 : t.getPjfs().doubleValue())
                        .average()
                        .orElse(0.0)
        ).setScale(2, RoundingMode.HALF_UP)
                .doubleValue();// 本月平均风速

        double lastYearWindSpeed = new BigDecimal(
                tqturbineList.stream()
                        .mapToDouble(t -> t.getPjfs() == null ? 0 : t.getPjfs().doubleValue())
                        .average()
                        .orElse(0.0)
        ).setScale(2, RoundingMode.HALF_UP)
                .doubleValue(); // 去年同期平均风速


        double currentUtilization = DoubleUtils.getRoundingNum(currentPower / sbrl, 0); // 本月利用小时
        double lastYearUtilization = DoubleUtils.getRoundingNum(lastYearPower / sbrl, 0);
        ; // 去年同期利用小时

        //计划运行时间
        int jhyxsj = daysInMonth * 24;
        int tqjhyxsj = qnInMonth * 24;

        //运行时间
        double yxsj = turbineList.stream()
                .mapToDouble(t -> t.getYxMin() == null ? 0 : Math.round(t.getYxMin().doubleValue() * 100.0) / 100.0)
                .sum();
        double tqyxsj = tqturbineList.stream()
                .mapToDouble(t -> t.getYxMin() == null ? 0 : Math.round(t.getYxMin().doubleValue() * 100.0) / 100.0)
                .sum();

        // 计算本月设备可利用率
        double currentEquipmentUtilization = yxsj / jhyxsj * 100;
        // 格式化保留两位小数
        currentEquipmentUtilization = Double.parseDouble(String.format("%.2f", currentEquipmentUtilization));

        // 计算去年同期设备可利用率
        double lastYearEquipmentUtilization = tqyxsj / tqjhyxsj * 100;
        // 格式化保留两位小数
        lastYearEquipmentUtilization = Double.parseDouble(String.format("%.2f", lastYearEquipmentUtilization));

        //检修时间
        double jxsj = turbineList.stream()
                .mapToDouble(t -> t.getYxMin() == null ? 0 : Math.round(t.getYxMin().doubleValue() * 100.0) / 100.0)
                .sum();
        double tqjxsj = tqturbineList.stream()
                .mapToDouble(t -> t.getYxMin() == null ? 0 : Math.round(t.getYxMin().doubleValue() * 100.0) / 100.0)
                .sum();

        double currentEfficiencyCoefficient = (yxsj + jxsj) / jhyxsj * 100;
        currentEfficiencyCoefficient = Double.parseDouble(String.format("%.2f", currentEfficiencyCoefficient));
        // 本月等效可用系数
        double lastYearEfficiencyCoefficient = (tqyxsj + tqjxsj) / tqjhyxsj * 100; // 去年同期等效可用系数
        lastYearEfficiencyCoefficient = Double.parseDouble(String.format("%.2f", lastYearEfficiencyCoefficient));


        double currentSmallWindSpeed = new BigDecimal(
                turbineList.stream()
                        .mapToDouble(t -> t.getXfqrfs() == null ? 0 : t.getXfqrfs().doubleValue())
                        .average()
                        .orElse(0.0)
        ).setScale(2, RoundingMode.HALF_UP)
                .doubleValue(); // 本月小风切入风速
        double lastYearSmallWindSpeed = new BigDecimal(
                tqturbineList.stream()
                        .mapToDouble(t -> t.getXfqrfs() == null ? 0 : t.getXfqrfs().doubleValue())
                        .average()
                        .orElse(0.0)
        ).setScale(2, RoundingMode.HALF_UP)
                .doubleValue(); // 去年同期小风切入风速

//        double currentSmallWindRate = 0.95; // 本月小风切入合格率
//        double lastYearSmallWindRate = 0.93; // 去年同期小风切入合格率

        double currentRunningWindHours = turbineList.stream()
                .mapToDouble(t -> t.getYxfss() == null ? 0 : Math.round(t.getYxfss().doubleValue() * 100.0) / 100.0)
                .sum(); // 本月有效风时数
        double lastYearRunningWindHours = tqturbineList.stream()
                .mapToDouble(t -> t.getYxfss() == null ? 0 : Math.round(t.getYxfss().doubleValue() * 100.0) / 100.0)
                .sum(); // 去年同期有效风时数

        double currentFaultLossPower = turbineList.stream()
                .mapToDouble(t -> t.getGzss() == null ? 0 : Math.round(t.getGzss().doubleValue() * 100.0) / 100.0)
                .sum(); // 本月故障损失电量
        double lastYearFaultLossPower = tqturbineList.stream()
                .mapToDouble(t -> t.getGzss() == null ? 0 : Math.round(t.getGzss().doubleValue() * 100.0) / 100.0)
                .sum(); // 去年同期故障损失电量


        double currentDispatchLossPower = turbineList.stream()
                .mapToDouble(t -> t.getXdss() == null ? 0 : new BigDecimal(t.getXdss().doubleValue())
                        .setScale(2, BigDecimal.ROUND_HALF_UP) // 保留两位小数并四舍五入
                        .doubleValue())
                .sum();
        currentDispatchLossPower = new BigDecimal(currentDispatchLossPower)
                .setScale(2, BigDecimal.ROUND_HALF_UP) // 确保最后的结果保留两位小数
                .doubleValue();// 本月调度限电损失电量


        double lastYearDispatchLossPower = tqturbineList.stream()
                .mapToDouble(t -> t.getXdss() == null ? 0 : new BigDecimal(t.getXdss().doubleValue())
                        .setScale(2, BigDecimal.ROUND_HALF_UP) // 保留两位小数并四舍五入
                        .doubleValue())
                .sum();
        lastYearDispatchLossPower = new BigDecimal(lastYearDispatchLossPower)
                .setScale(2, BigDecimal.ROUND_HALF_UP) // 确保最后的结果保留两位小数
                .doubleValue();// 去年同期调度限电损失电量


        double currentPlannedMaintenanceLossPower = turbineList.stream()
                .mapToDouble(t -> t.getJhjxss() == null ? 0 : Math.round(t.getJhjxss().doubleValue() * 100.0) / 100.0)
                .sum(); // 本月计划检修损失电量
        double lastYearPlannedMaintenanceLossPower = tqturbineList.stream()
                .mapToDouble(t -> t.getJhjxss() == null ? 0 : Math.round(t.getJhjxss().doubleValue() * 100.0) / 100.0)
                .sum(); // 去年同期计划检修损失电量

        double currentPerformanceLossPower = turbineList.stream()
                .mapToDouble(t -> t.getXnss() == null ? 0 : new BigDecimal(t.getXnss().doubleValue())
                        .setScale(2, BigDecimal.ROUND_HALF_UP) // 保留两位小数并四舍五入
                        .doubleValue())
                .sum(); // 本月性能未达标损失电量
        currentPerformanceLossPower = new BigDecimal(currentPerformanceLossPower)
                .setScale(2, BigDecimal.ROUND_HALF_UP) // 确保最后的结果保留两位小数
                .doubleValue();


        double lastYearPerformanceLossPower = tqturbineList.stream()
                .mapToDouble(t -> t.getXnss() == null ? 0 : new BigDecimal(t.getXnss().doubleValue())
                        .setScale(2, BigDecimal.ROUND_HALF_UP) // 保留两位小数并四舍五入
                        .doubleValue())
                .sum(); // 去年同期性能未达标损失电量
        lastYearPerformanceLossPower = new BigDecimal(lastYearPerformanceLossPower)
                .setScale(2, BigDecimal.ROUND_HALF_UP)
                .doubleValue();


        double currentFaultDowntime = turbineList.stream()
                .mapToDouble(t -> t.getGzMin() == null ? 0 : Math.round(t.getGzMin().doubleValue() * 100.0) / 100.0)
                .sum(); // 本月故障停运时间
        double lastYearFaultDowntime = tqturbineList.stream()
                .mapToDouble(t -> t.getGzMin() == null ? 0 : Math.round(t.getGzMin().doubleValue() * 100.0) / 100.0)
                .sum(); // 去年同期故障停运时间

        double currentMaintenanceDowntime = jxsj; // 本月检修停运时间
        double lastYearMaintenanceDowntime = tqjxsj; // 去年同期检修停运时间

        double currentGridConnectionTime = turbineList.stream()
                .mapToDouble(t -> t.getYxMin() == null ? 0 : Math.round(t.getYxMin().doubleValue() * 100.0) / 100.0)
                .sum(); // 本月并网时间
        double lastYearGridConnectionTime = tqturbineList.stream()
                .mapToDouble(t -> t.getYxMin() == null ? 0 : Math.round(t.getYxMin().doubleValue() * 100.0) / 100.0)
                .sum(); // 去年同期并网时间

        double currentStandbyTime = turbineList.stream()
                .mapToDouble(t -> t.getDjMin() == null ? 0 : Math.round(t.getDjMin().doubleValue() * 100.0) / 100.0)
                .sum(); // 本月待机时间
        double lastYearStandbyTime = tqturbineList.stream()
                .mapToDouble(t -> t.getDjMin() == null ? 0 : Math.round(t.getDjMin().doubleValue() * 100.0) / 100.0)
                .sum(); // 去年同期待机时间

        double currentCommFailureTime = turbineList.stream()
                .mapToDouble(t -> t.getTjMin() == null ? 0 : Math.round(t.getTjMin().doubleValue() * 100.0) / 100.0)
                .sum(); // 本月通讯中断时间
        double lastYearCommFailureTime = tqturbineList.stream()
                .mapToDouble(t -> t.getTjMin() == null ? 0 : Math.round(t.getTjMin().doubleValue() * 100.0) / 100.0)
                .sum(); // 去年同期通讯中断时间

        double currentCalmWindFrequency = turbineList.stream()
                .mapToDouble(t -> t.getJfpl() == null ? 0 : Math.round(t.getJfpl().doubleValue() * 100.0) / 100.0)
                .sum(); // 本月静风频率
        double lastYearCalmWindFrequency = tqturbineList.stream()
                .mapToDouble(t -> t.getJfpl() == null ? 0 : Math.round(t.getJfpl().doubleValue() * 100.0) / 100.0)
                .sum(); // 去年同期静风频率

        // 使用方法来简化添加数据
        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 = calculateGrowthRate(currentPower, lastYearPower);//发电量增长率
        double ssdllj = currentFaultLossPower + currentDispatchLossPower + currentPlannedMaintenanceLossPower + currentPerformanceLossPower; //损失电量合计
        double tqssdllj = lastYearFaultLossPower + lastYearDispatchLossPower + lastYearPlannedMaintenanceLossPower + lastYearPerformanceLossPower;//同期损失电量合计
        double ssdlzzl = calculateGrowthRate(ssdllj, tqssdllj);
        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))
        );
    }
}
