package com.hdkj.lt.bf.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hdkj.lt.bf.application.FeederGroupApplication;
import com.hdkj.lt.bf.entity.FhzgDwmVoltageOverLimitDaily;
import com.hdkj.lt.bf.entity.FhzgSeCapacityDaily;
import com.hdkj.lt.bf.entity.FhzgSeVoltageEvent;
import com.hdkj.lt.bf.entity.FhzgSeSnapshotDetail;
import com.hdkj.lt.bf.entity.dto.TodayOutageData;
import com.hdkj.lt.bf.entity.vo.SeCapacityDashboardVO;
import com.hdkj.lt.bf.entity.vo.SeOutageDashboardVO;
import com.hdkj.lt.bf.entity.vo.SeVoltageDashboardVO;
import com.hdkj.lt.bf.mapper.FhzgDwmVoltageOverLimitDailyMapper;
import com.hdkj.lt.bf.mapper.FhzgSeCapacityDailyMapper;
import com.hdkj.lt.bf.mapper.FhzgSeVoltageEventMapper;
import com.hdkj.lt.bf.mapper.FhzgSeSnapshotDetailMapper;
import com.hdkj.lt.bf.service.SeIndicatorService;
import com.hdkj.lt.bf.service.SjztPwwyyqxtPrmPdrOutageMvDsService;
import com.hdkj.fhzg.optimization.response.FeederGroupTreeNode;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 状估监测体系 三个查询接口 Service 实现
 *
 * @author lsl
 * @since 2026-07-23
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class SeIndicatorServiceImpl implements SeIndicatorService {

    private final SjztPwwyyqxtPrmPdrOutageMvDsService outageService;
    private final FhzgSeVoltageEventMapper voltageEventMapper;
    private final FhzgDwmVoltageOverLimitDailyMapper voltageDailyMapper;
    private final FhzgSeSnapshotDetailMapper snapshotDetailMapper;
    private final FhzgSeCapacityDailyMapper capacityDailyMapper;
    private final FeederGroupApplication feederGroupApplication;

    private static final DateTimeFormatter DATE_FMT = DateTimeFormatter.ofPattern("yyyyMMdd");

    // ============================================================
    // 1. 停电时户数（复用已有逻辑，无时间维度）
    // ============================================================

    @Override
    public SeOutageDashboardVO queryOutage(String id, Integer type) {
        if (StringUtils.isBlank(id) || type == null) {
            return null;
        }

        // 今日 — 实时表
        TodayOutageData today = outageService.getTodayOutageData(id, type);

        // 全年（1.1 ~ 昨天）— T-2表
        LocalDate todayDate = LocalDate.now();
        int year = todayDate.getYear();
        LocalDateTime yearStart = LocalDate.of(year, 1, 1).atStartOfDay();
        LocalDateTime yesterdayEnd = todayDate.minusDays(1).atTime(23, 59, 59);
        TodayOutageData yearStats = outageService.getOutageDurationHoursHouseholds(id, type, yearStart, yesterdayEnd);

        return SeOutageDashboardVO.builder()
                .outageHoursHouseholdsToday(today.getTotalHouseholds())
                .avgOutageDurationToday(today.getAvgDurationHours())
                .outageHoursHouseholdsYear(yearStats.getTotalHouseholds())
                .avgOutageDurationYear(yearStats.getAvgDurationHours())
                .build();
    }

    // ============================================================
    // 2. 电压质量
    // ============================================================

    @Override
    public SeVoltageDashboardVO queryVoltage(String id, Integer type, String timeScope) {
        if (StringUtils.isBlank(id) || type == null || StringUtils.isBlank(timeScope)) {
            return null;
        }

        if ("today".equalsIgnoreCase(timeScope)) {
            return queryVoltageToday(id, type);
        } else {
            return queryVoltageHistory(id, type, timeScope);
        }
    }

    /**
     * 今日电压：COUNT 聚合到 SQL，按 alarmLevel + alarmType 分组
     * 返回4个计数：台区越上限/下限 + 馈线越上限/下限
     */
    private SeVoltageDashboardVO queryVoltageToday(String id, Integer type) {
        LocalDateTime todayStart = LocalDate.now().atStartOfDay();
        LocalDateTime now = LocalDateTime.now();

        int overUpperArea = countVoltageEvents(id, type, todayStart, now, "mvtrans", "over");
        int overLowerArea = countVoltageEvents(id, type, todayStart, now, "mvtrans", "under");
        int overUpperFeeder = countVoltageEvents(id, type, todayStart, now, "feeder", "over");
        int overLowerFeeder = countVoltageEvents(id, type, todayStart, now, "feeder", "under");

        return SeVoltageDashboardVO.builder()
                .todayOverUpperAreaCount(overUpperArea)
                .todayOverLowerAreaCount(overLowerArea)
                .todayOverUpperFeederCount(overUpperFeeder)
                .todayOverLowerFeederCount(overLowerFeeder)
                .build();
    }

    /**
     * 按节点+时段+类型统计电压越限事件数
     */
    private int countVoltageEvents(String id, Integer type,
                                    LocalDateTime start, LocalDateTime end,
                                    String alarmLevel, String overOrUnder) {
        LambdaQueryWrapper<FhzgSeVoltageEvent> wrapper = new LambdaQueryWrapper<FhzgSeVoltageEvent>()
                .ge(FhzgSeVoltageEvent::getTriggerTime, start)
                .le(FhzgSeVoltageEvent::getTriggerTime, end)
                .eq(FhzgSeVoltageEvent::getStatus, 1)
                .eq(FhzgSeVoltageEvent::getAlarmLevel, alarmLevel)
                .like(FhzgSeVoltageEvent::getAlarmType, overOrUnder);
        applyNodeFilter(wrapper, id, type);
        Long count = voltageEventMapper.selectCount(wrapper);
        return count != null ? count.intValue() : 0;
    }

    /**
     * 历史电压：查 ads_mrt_voltage_over_limit_daily_result，SUM 聚合到 SQL
     * 当月 = 月初~昨天；全年 = 1.1~昨天
     * 17:00前查历史当月/全年 = 中台[到前天] + 我们alarm_event[昨天]；17:00后 = 中台[到昨天]
     */
    private SeVoltageDashboardVO queryVoltageHistory(String id, Integer type, String timeScope) {
        LocalDate today = LocalDate.now();
        LocalDate endDate;
        LocalDate startDate;

        if ("month".equalsIgnoreCase(timeScope)) {
            startDate = today.withDayOfMonth(1);
        } else {
            startDate = LocalDate.of(today.getYear(), 1, 1);
        }

        // 17:00前：中台到前天 + 我们昨天；17:00后：中台到昨天
        int hour = LocalDateTime.now().getHour();
        if (hour < 17) {
            endDate = today.minusDays(2);
        } else {
            endDate = today.minusDays(1);
        }

        // 如果 endDate < startDate，返回空
        if (endDate.isBefore(startDate)) {
            return SeVoltageDashboardVO.builder().build();
        }

        String dimLevel = resolveDimLevel(type);

        // 一条 SQL 聚合 16个count字段 + total_over_limit_hours
        QueryWrapper<FhzgDwmVoltageOverLimitDaily> qw = new QueryWrapper<>();
        qw.select(
                "COALESCE(SUM(over_upper_severe_tg_count),0) AS over_upper_severe_tg_count",
                "COALESCE(SUM(over_upper_severe_cust_count),0) AS over_upper_severe_cust_count",
                "COALESCE(SUM(over_upper_severe_feeder_count),0) AS over_upper_severe_feeder_count",
                "COALESCE(SUM(over_upper_severe_generatrix_count),0) AS over_upper_severe_generatrix_count",
                "COALESCE(SUM(over_upper_mild_tg_count),0) AS over_upper_mild_tg_count",
                "COALESCE(SUM(over_upper_mild_cust_count),0) AS over_upper_mild_cust_count",
                "COALESCE(SUM(over_upper_mild_feeder_count),0) AS over_upper_mild_feeder_count",
                "COALESCE(SUM(over_upper_mild_generatrix_count),0) AS over_upper_mild_generatrix_count",
                "COALESCE(SUM(over_lower_severe_tg_count),0) AS over_lower_severe_tg_count",
                "COALESCE(SUM(over_lower_severe_cust_count),0) AS over_lower_severe_cust_count",
                "COALESCE(SUM(over_lower_severe_feeder_count),0) AS over_lower_severe_feeder_count",
                "COALESCE(SUM(over_lower_severe_generatrix_count),0) AS over_lower_severe_generatrix_count",
                "COALESCE(SUM(over_lower_mild_tg_count),0) AS over_lower_mild_tg_count",
                "COALESCE(SUM(over_lower_mild_cust_count),0) AS over_lower_mild_cust_count",
                "COALESCE(SUM(over_lower_mild_feeder_count),0) AS over_lower_mild_feeder_count",
                "COALESCE(SUM(over_lower_mild_generatrix_count),0) AS over_lower_mild_generatrix_count",
                "COALESCE(SUM(total_over_limit_hours),0) AS total_over_limit_hours")
                .eq("dim_level", dimLevel)
                .ge("over_date", startDate.format(DATE_FMT))
                .le("over_date", endDate.format(DATE_FMT));

        // 维度过滤
        if (type == 2) {
            qw.eq("maintainer_id", id);
        } else if (type == 3) {
            qw.eq("substation_id", id);
        } else if (type == 4) {
            qw.eq("feeder_id", id);
        }

        List<FhzgDwmVoltageOverLimitDaily> records = voltageDailyMapper.selectList(qw);
        FhzgDwmVoltageOverLimitDaily r = (records != null && !records.isEmpty()) ? records.get(0) : null;

        int overUpperSevereTg = r != null ? safeInt(r.getOverUpperSevereTgCount()) : 0;
        int overUpperSevereCust = r != null ? safeInt(r.getOverUpperSevereCustCount()) : 0;
        int overUpperSevereFeeder = r != null ? safeInt(r.getOverUpperSevereFeederCount()) : 0;
        int overUpperSevereGen = r != null ? safeInt(r.getOverUpperSevereGeneratrixCount()) : 0;
        int overUpperMildTg = r != null ? safeInt(r.getOverUpperMildTgCount()) : 0;
        int overUpperMildCust = r != null ? safeInt(r.getOverUpperMildCustCount()) : 0;
        int overUpperMildFeeder = r != null ? safeInt(r.getOverUpperMildFeederCount()) : 0;
        int overUpperMildGen = r != null ? safeInt(r.getOverUpperMildGeneratrixCount()) : 0;
        int overLowerSevereTg = r != null ? safeInt(r.getOverLowerSevereTgCount()) : 0;
        int overLowerSevereCust = r != null ? safeInt(r.getOverLowerSevereCustCount()) : 0;
        int overLowerSevereFeeder = r != null ? safeInt(r.getOverLowerSevereFeederCount()) : 0;
        int overLowerSevereGen = r != null ? safeInt(r.getOverLowerSevereGeneratrixCount()) : 0;
        int overLowerMildTg = r != null ? safeInt(r.getOverLowerMildTgCount()) : 0;
        int overLowerMildCust = r != null ? safeInt(r.getOverLowerMildCustCount()) : 0;
        int overLowerMildFeeder = r != null ? safeInt(r.getOverLowerMildFeederCount()) : 0;
        int overLowerMildGen = r != null ? safeInt(r.getOverLowerMildGeneratrixCount()) : 0;
        BigDecimal totalHours = r != null && r.getTotalOverLimitHours() != null
                ? r.getTotalOverLimitHours() : BigDecimal.ZERO;

        // 17:00前补昨日数据（从我们alarm_event查昨天）
        if (hour < 17) {
            LocalDateTime yesterdayStart = today.minusDays(1).atStartOfDay();
            LocalDateTime yesterdayEnd = today.minusDays(1).atTime(23, 59, 59);
            LambdaQueryWrapper<FhzgSeVoltageEvent> yesterdayWrapper = new LambdaQueryWrapper<FhzgSeVoltageEvent>()
                    .ge(FhzgSeVoltageEvent::getTriggerTime, yesterdayStart)
                    .le(FhzgSeVoltageEvent::getTriggerTime, yesterdayEnd)
                    .eq(FhzgSeVoltageEvent::getStatus, 2);
            applyNodeFilter(yesterdayWrapper, id, type);
            List<FhzgSeVoltageEvent> yesterdayEvents = voltageEventMapper.selectList(yesterdayWrapper);
            for (FhzgSeVoltageEvent e : yesterdayEvents) {
                if ("voltage_over".equals(e.getAlarmType()) || e.getAlarmType() != null && e.getAlarmType().contains("over")) {
                    overUpperMildTg++;
                } else if (e.getAlarmType() != null && e.getAlarmType().contains("under")) {
                    overLowerMildTg++;
                }
            }
        }

        return SeVoltageDashboardVO.builder()
                .overUpperSevereTgCount(overUpperSevereTg)
                .overUpperSevereCustCount(overUpperSevereCust)
                .overUpperSevereFeederCount(overUpperSevereFeeder)
                .overUpperSevereGeneratrixCount(overUpperSevereGen)
                .overUpperMildTgCount(overUpperMildTg)
                .overUpperMildCustCount(overUpperMildCust)
                .overUpperMildFeederCount(overUpperMildFeeder)
                .overUpperMildGeneratrixCount(overUpperMildGen)
                .overLowerSevereTgCount(overLowerSevereTg)
                .overLowerSevereCustCount(overLowerSevereCust)
                .overLowerSevereFeederCount(overLowerSevereFeeder)
                .overLowerSevereGeneratrixCount(overLowerSevereGen)
                .overLowerMildTgCount(overLowerMildTg)
                .overLowerMildCustCount(overLowerMildCust)
                .overLowerMildFeederCount(overLowerMildFeeder)
                .overLowerMildGeneratrixCount(overLowerMildGen)
                .totalOverLimitHours(totalHours)
                .build();
    }

    // ============================================================
    // 3. 供电能力
    // ============================================================

    @Override
    public SeCapacityDashboardVO queryCapacity(String id, Integer type, String timeScope) {
        if (StringUtils.isBlank(id) || type == null || StringUtils.isBlank(timeScope)) {
            return null;
        }

        // 今日 → 实时查断面明细（量小）
        if ("today".equalsIgnoreCase(timeScope)) {
            return queryCapacityToday(id, type);
        }

        // month/year → 查日汇总表
        return queryCapacityHistory(id, type, timeScope);
    }

    /**
     * 今日供电能力：实时查 snapshot_detail（量小，一个馈线一天最多96行）
     * 馈线级别附加96点时序（负载率+电流+电压+有功+无功）
     */
    private SeCapacityDashboardVO queryCapacityToday(String id, Integer type) {
        LocalDate today = LocalDate.now();
        LocalDateTime startTime = today.atStartOfDay();
        LocalDateTime endTime = LocalDateTime.now();

        LambdaQueryWrapper<FhzgSeSnapshotDetail> wrapper = new LambdaQueryWrapper<FhzgSeSnapshotDetail>()
                .eq(FhzgSeSnapshotDetail::getDeviceType, "feeder")
                .isNotNull(FhzgSeSnapshotDetail::getLoadRate)
                .ge(FhzgSeSnapshotDetail::getSnapshotTime, startTime)
                .le(FhzgSeSnapshotDetail::getSnapshotTime, endTime);

        applySnapshotFilter(wrapper, id, type);

        List<FhzgSeSnapshotDetail> snapshots = snapshotDetailMapper.selectList(wrapper);

        if (snapshots.isEmpty()) {
            return SeCapacityDashboardVO.builder().build();
        }

        SeCapacityDashboardVO vo = aggregateSnapshots(snapshots);

        // 馈线 → 附加96点时序
        if (type == 4) {
            vo.setLoadRateSeries(buildFeederTimeSeries(snapshots));
        }
        return vo;
    }

    /**
     * 历史供电能力：查 capacity_daily 日汇总表（每馈线每天一行，量极小）
     * month = 月初~昨天；year = 1.1~昨天
     */
    private SeCapacityDashboardVO queryCapacityHistory(String id, Integer type, String timeScope) {
        LocalDate today = LocalDate.now();
        LocalDate startDate;
        LocalDate endDate;

        if ("month".equalsIgnoreCase(timeScope)) {
            startDate = today.withDayOfMonth(1);
        } else {
            startDate = LocalDate.of(today.getYear(), 1, 1);
        }
        endDate = today.minusDays(1);

        if (endDate.isBefore(startDate)) {
            return SeCapacityDashboardVO.builder().build();
        }

        LambdaQueryWrapper<FhzgSeCapacityDaily> wrapper = new LambdaQueryWrapper<FhzgSeCapacityDaily>()
                .ge(FhzgSeCapacityDaily::getStatDate, startDate)
                .le(FhzgSeCapacityDaily::getStatDate, endDate);

        applyCapacityDailyFilter(wrapper, id, type);

        List<FhzgSeCapacityDaily> dailyRecords = capacityDailyMapper.selectList(wrapper);

        if (dailyRecords.isEmpty()) {
            return SeCapacityDashboardVO.builder().build();
        }

        // 聚合日汇总
        BigDecimal maxLoadRate = BigDecimal.ZERO;
        BigDecimal sumAvg = BigDecimal.ZERO;
        int totalHeavy = 0, totalOverload = 0, totalSnapshots = 0;
        for (FhzgSeCapacityDaily d : dailyRecords) {
            if (d.getMaxLoadRate() != null && d.getMaxLoadRate().compareTo(maxLoadRate) > 0) {
                maxLoadRate = d.getMaxLoadRate();
            }
            if (d.getAvgLoadRate() != null) {
                sumAvg = sumAvg.add(d.getAvgLoadRate());
            }
            totalHeavy += d.getHeavyCount() != null ? d.getHeavyCount() : 0;
            totalOverload += d.getOverloadCount() != null ? d.getOverloadCount() : 0;
            totalSnapshots += d.getTotalSnapshots() != null ? d.getTotalSnapshots() : 0;
        }

        int totalEvents = totalHeavy + totalOverload;
        int recordCount = dailyRecords.size();
        BigDecimal avgLoadRate = recordCount > 0
                ? sumAvg.divide(BigDecimal.valueOf(recordCount), 2, RoundingMode.HALF_UP)
                : BigDecimal.ZERO;
        BigDecimal heavyRate = totalSnapshots > 0
                ? BigDecimal.valueOf(totalHeavy * 100).divide(BigDecimal.valueOf(totalSnapshots), 2, RoundingMode.HALF_UP)
                : BigDecimal.ZERO;
        BigDecimal overloadRate = totalSnapshots > 0
                ? BigDecimal.valueOf(totalOverload * 100).divide(BigDecimal.valueOf(totalSnapshots), 2, RoundingMode.HALF_UP)
                : BigDecimal.ZERO;

        return SeCapacityDashboardVO.builder()
                .maxLoadRate(maxLoadRate)
                .avgLoadRate(avgLoadRate)
                .heavyLoadEventCount(totalHeavy)
                .overloadEventCount(totalOverload)
                .heavyLoadRate(heavyRate)
                .overloadRate(overloadRate)
                .totalEventCount(totalEvents)
                .build();
    }

    /**
     * 内存聚合断面列表 → VO（today用）
     */
    private SeCapacityDashboardVO aggregateSnapshots(List<FhzgSeSnapshotDetail> snapshots) {
        BigDecimal maxLoadRate = snapshots.stream()
                .map(FhzgSeSnapshotDetail::getLoadRate)
                .filter(Objects::nonNull)
                .reduce(BigDecimal::max)
                .orElse(BigDecimal.ZERO);

        BigDecimal avgLoadRate = snapshots.stream()
                .map(FhzgSeSnapshotDetail::getLoadRate)
                .filter(Objects::nonNull)
                .reduce(BigDecimal.ZERO, BigDecimal::add)
                .divide(BigDecimal.valueOf(snapshots.size()), 2, RoundingMode.HALF_UP);

        int heavyCount = 0, overloadCount = 0;
        for (FhzgSeSnapshotDetail s : snapshots) {
            Integer status = s.getCurrentStatus();
            if (status != null) {
                if (status == 1) heavyCount++;
                if (status == 2) overloadCount++;
            }
        }
        int totalEvents = heavyCount + overloadCount;
        int totalSnapshots = snapshots.size();
        BigDecimal heavyRate = totalSnapshots > 0
                ? BigDecimal.valueOf(heavyCount * 100).divide(BigDecimal.valueOf(totalSnapshots), 2, RoundingMode.HALF_UP)
                : BigDecimal.ZERO;
        BigDecimal overloadRate = totalSnapshots > 0
                ? BigDecimal.valueOf(overloadCount * 100).divide(BigDecimal.valueOf(totalSnapshots), 2, RoundingMode.HALF_UP)
                : BigDecimal.ZERO;

        return SeCapacityDashboardVO.builder()
                .maxLoadRate(maxLoadRate)
                .avgLoadRate(avgLoadRate)
                .heavyLoadEventCount(heavyCount)
                .overloadEventCount(overloadCount)
                .heavyLoadRate(heavyRate)
                .overloadRate(overloadRate)
                .totalEventCount(totalEvents)
                .build();
    }

    /**
     * 构建馈线今日96点时序（负载率+电流+电压+有功+无功）
     */
    private List<SeCapacityDashboardVO.TimeSeriesPoint> buildFeederTimeSeries(List<FhzgSeSnapshotDetail> snapshots) {
        DateTimeFormatter hmFmt = DateTimeFormatter.ofPattern("HH:mm");
        return snapshots.stream()
                .sorted(Comparator.comparing(FhzgSeSnapshotDetail::getSnapshotTime))
                .map(s -> SeCapacityDashboardVO.TimeSeriesPoint.builder()
                        .time(s.getSnapshotTime().format(hmFmt))
                        .loadRate(s.getLoadRate())
                        .currentValue(s.getCurrentValue())
                        .voltageValue(s.getVoltageValue())
                        .activePower(s.getActivePower())
                        .reactivePower(s.getReactivePower())
                        .build())
                .collect(Collectors.toList());
    }

    // ============================================================
    // 辅助方法
    // ============================================================

    private void applyNodeFilter(LambdaQueryWrapper<FhzgSeVoltageEvent> wrapper, String id, Integer type) {
        if (type == 2) {
            wrapper.eq(FhzgSeVoltageEvent::getCountyId, id);
        } else if (type == 3) {
            wrapper.eq(FhzgSeVoltageEvent::getSubsId, id);
        } else if (type == 4) {
            wrapper.eq(FhzgSeVoltageEvent::getFeederId, id);
        }
    }

    private void applySnapshotFilter(LambdaQueryWrapper<FhzgSeSnapshotDetail> wrapper, String id, Integer type) {
        if (type == 2) {
            wrapper.eq(FhzgSeSnapshotDetail::getCountyId, id);
        } else if (type == 3) {
            wrapper.eq(FhzgSeSnapshotDetail::getSubsId, id);
        } else if (type == 4) {
            wrapper.eq(FhzgSeSnapshotDetail::getFeederId, id);
        }
    }

    private void applyCapacityDailyFilter(LambdaQueryWrapper<FhzgSeCapacityDaily> wrapper, String id, Integer type) {
        if (type == 2) {
            wrapper.eq(FhzgSeCapacityDaily::getCountyId, id);
        } else if (type == 3) {
            wrapper.eq(FhzgSeCapacityDaily::getSubsId, id);
        } else if (type == 4) {
            wrapper.eq(FhzgSeCapacityDaily::getFeederId, id);
        }
    }

    private String resolveDimLevel(Integer type) {
        if (type == 2) return "county";
        if (type == 3) return "substation";
        if (type == 4) return "feeder";
        return "county";
    }

    private int safeInt(Integer v) {
        return v == null ? 0 : v;
    }
}