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

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hdkj.lt.bf.entity.FhzgSeCapacityDaily;
import com.hdkj.lt.bf.entity.staticgrid.StaticIndicatorMetric;
import com.hdkj.lt.bf.entity.staticgrid.StaticIndicatorResult;
import com.hdkj.lt.bf.entity.vo.StaticGridDashboardVO;
import com.hdkj.lt.bf.mapper.FhzgSeCapacityDailyMapper;
import com.hdkj.lt.bf.mapper.staticgrid.StaticIndicatorMetricMapper;
import com.hdkj.lt.bf.mapper.staticgrid.StaticIndicatorResultMapper;
import com.hdkj.lt.bf.service.SjztPwwyyqxtPrmPdrOutageMvDsService;
import com.hdkj.lt.bf.service.staticgrid.StaticGridDashboardService;
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.YearMonth;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 静态网架评估仪表盘服务实现
 * <p>
 * 支持三种节点维度查询：
 * <ul>
 *   <li>type=2 区县 — 取 county 级指标</li>
 *   <li>type=3 变电站 — 聚合该变电站下所有馈线的 feeder 级指标</li>
 *   <li>type=4 馈线 — 取单条馈线的 feeder 级指标（聚合后 bool→0/1、rate→0%/100%）</li>
 * </ul>
 * 静态指标按月份过滤，前端传 daytime（如 2026-7-16），取该月最新一批数据。
 * 停电时户数通过 SjztPwwyyqxtPrmPdrOutageMvDsService 获取。
 *
 * @author lsl
 * @since 2026-07-19
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class StaticGridDashboardServiceImpl
        extends ServiceImpl<StaticIndicatorResultMapper, StaticIndicatorResult>
        implements StaticGridDashboardService {

    private final StaticIndicatorMetricMapper metricMapper;
    private final SjztPwwyyqxtPrmPdrOutageMvDsService outageDurationService;
    private final FhzgSeCapacityDailyMapper capacityDailyMapper;

    // ============================================================
    // 指标聚合映射表：county 级 metric_code → feeder 级 metric_code
    // ============================================================

    /** 布尔计数类：count(value="true") */
    private static final Map<String, String> BOOL_COUNT_MAP = new LinkedHashMap<>();
    static {
        BOOL_COUNT_MAP.put("same_bus_interconnection_issue_count", "has_same_bus_interconnection_issue");
        BOOL_COUNT_MAP.put("excessive_tie_point_feeder_count", "has_excessive_tie_points");
        BOOL_COUNT_MAP.put("single_radial_feeder_count", "is_single_radial_feeder");
        BOOL_COUNT_MAP.put("large_branch_issue_feeder_count", "has_large_branch_issue");
        BOOL_COUNT_MAP.put("main_trunk_lantern_issue_feeder_count", "has_main_trunk_lantern_issue");
        BOOL_COUNT_MAP.put("unreasonable_segment_count_feeder_count", "has_unreasonable_segment_count");
        BOOL_COUNT_MAP.put("supply_radius_exceed_feeder_count", "is_supply_radius_exceeded");
        BOOL_COUNT_MAP.put("extra_long_feeder_count", "is_extra_long_feeder");
        BOOL_COUNT_MAP.put("main_trunk_bottleneck_feeder_count", "has_main_trunk_bottleneck");
        BOOL_COUNT_MAP.put("connected_capacity_exceed_feeder_count", "is_connected_capacity_exceeded");
    }

    /** 布尔比率类：count(true)/total×100 */
    private static final Map<String, String> BOOL_RATE_MAP = new LinkedHashMap<>();
    static {
        BOOL_RATE_MAP.put("wiring_standardization_rate", "is_standard_wiring");
        BOOL_RATE_MAP.put("main_trunk_section_standardization_rate", "main_trunk_section_compliant");
        BOOL_RATE_MAP.put("n_minus_1_pass_rate", "n_minus_1_passed");
        BOOL_RATE_MAP.put("line_interconnection_rate", "has_tie");
        BOOL_RATE_MAP.put("inter_substation_interconnection_rate", "has_inter_substation_tie");
    }

    /** 整数求和类：sum(value) */
    private static final Map<String, String> INT_SUM_MAP = new LinkedHashMap<>();
    static {
        INT_SUM_MAP.put("feeder_head_tie_point_issue_count", "feeder_head_tie_point_issue_count");
        INT_SUM_MAP.put("same_pole_tie_point_issue_count", "same_pole_tie_point_issue_count");
        INT_SUM_MAP.put("load_group_capacity_anomaly_count", "load_group_capacity_anomaly_count");
        INT_SUM_MAP.put("main_trunk_total_count", "main_trunk_count");
        INT_SUM_MAP.put("section_compliant_main_trunk_count", "section_compliant_main_trunk_count");
    }

    // ============================================================
    // 主入口
    // ============================================================

    @Override
    public StaticGridDashboardVO queryLatestDashboard(String id, String type) {
        if (StringUtils.isBlank(id) || StringUtils.isBlank(type)) {
            log.warn("参数缺失: id={}, type={}", id, type);
            return null;
        }

        int nodeType;
        try {
            nodeType = Integer.parseInt(type);
        } catch (NumberFormatException e) {
            log.warn("type 参数非法: {}", type);
            return null;
        }

        YearMonth ym = YearMonth.now();
        if (nodeType == 2) {
            return queryByCounty(id, ym);
        } else if (nodeType == 3) {
            return queryBySubstation(id, ym);
        } else if (nodeType == 4) {
            return queryByFeeder(id, ym);
        }
        log.warn("不支持的节点类型: {}", nodeType);
        return null;
    }

    // ============================================================
    // 三种维度的查询路径
    // ============================================================

    /**
     * type=2 区县：主表按 maintOrgId + 月份查最新，取 county 级指标
     */
    private StaticGridDashboardVO queryByCounty(String maintOrgId, YearMonth ym) {
        StaticIndicatorResult result = getLatestByMaintOrgId(maintOrgId, ym);
        if (result == null) {
            log.warn("区县无静态网架数据 maintOrgId={}, month={}", maintOrgId, ym);
            return null;
        }
        // county 级指标
        List<StaticIndicatorMetric> countyMetrics = getMetrics(result.getId(), "county", null, null);
        Map<String, String> metricMap = metricsToMap(countyMetrics);
        // 停电时户数
        BigDecimal outage = outageDurationService.getOutageDurationHoursHouseholds(
                maintOrgId, 2,
                ym.atDay(1).atStartOfDay(),
                ym.atEndOfMonth().atTime(23, 59, 59)).getTotalHouseholds();
        StaticGridDashboardVO vo = buildDashboardVO(result, metricMap, outage);
        fillCapacityMetrics(vo, result.getCountyId(), null, null, ym);
        return vo;
    }

    /**
     * type=3 变电站：先查该月所有主表批次，再按 sourceSubstationId 过滤 feeder 级指标，聚合
     */
    private StaticGridDashboardVO queryBySubstation(String substationId, YearMonth ym) {
        List<Long> resultIds = getResultIdsByMonth(ym);
        if (resultIds.isEmpty()) {
            log.warn("月份无静态网架数据 month={}", ym);
            return null;
        }
        LambdaQueryWrapper<StaticIndicatorMetric> wrapper = new LambdaQueryWrapper<StaticIndicatorMetric>()
                .in(StaticIndicatorMetric::getResultId, resultIds)
                .eq(StaticIndicatorMetric::getLevel, "feeder")
                .eq(StaticIndicatorMetric::getSourceSubstationId, substationId);
        List<StaticIndicatorMetric> feederMetrics = metricMapper.selectList(wrapper);
        if (feederMetrics.isEmpty()) {
            log.warn("变电站无 feeder 级指标 substationId={}", substationId);
            return null;
        }
        Long resultId = feederMetrics.get(0).getResultId();
        StaticIndicatorResult result = getById(resultId);
        Map<String, String> metricMap = aggregateFeederMetrics(feederMetrics);
        BigDecimal outage = outageDurationService.getOutageDurationHoursHouseholds(
                substationId, 3,
                ym.atDay(1).atStartOfDay(),
                ym.atEndOfMonth().atTime(23, 59, 59)).getTotalHouseholds();
        StaticGridDashboardVO vo = buildDashboardVO(result, metricMap, outage);
        fillCapacityMetrics(vo, null, substationId, null, ym);
        return vo;
    }

    /**
     * type=4 馈线：按 feederId 查 feeder 级指标，聚合（单条馈线 → bool 转 0/1，rate 转 0%/100%）
     */
    private StaticGridDashboardVO queryByFeeder(String feederId, YearMonth ym) {
        List<Long> resultIds = getResultIdsByMonth(ym);
        if (resultIds.isEmpty()) {
            log.warn("月份无静态网架数据 month={}", ym);
            return null;
        }
        LambdaQueryWrapper<StaticIndicatorMetric> wrapper = new LambdaQueryWrapper<StaticIndicatorMetric>()
                .in(StaticIndicatorMetric::getResultId, resultIds)
                .eq(StaticIndicatorMetric::getLevel, "feeder")
                .eq(StaticIndicatorMetric::getFeederId, feederId);
        List<StaticIndicatorMetric> feederMetrics = metricMapper.selectList(wrapper);
        if (feederMetrics.isEmpty()) {
            log.warn("馈线无 feeder 级指标 feederId={}", feederId);
            return null;
        }
        Long resultId = feederMetrics.get(0).getResultId();
        StaticIndicatorResult result = getById(resultId);
        Map<String, String> metricMap = aggregateFeederMetrics(feederMetrics);
        BigDecimal outage = outageDurationService.getOutageDurationHoursHouseholds(
                feederId, 4,
                ym.atDay(1).atStartOfDay(),
                ym.atEndOfMonth().atTime(23, 59, 59)).getTotalHouseholds();
        StaticGridDashboardVO vo = buildDashboardVO(result, metricMap, outage);
        fillCapacityMetrics(vo, null, null, feederId, ym);
        return vo;
    }

    // ============================================================
    // 聚合逻辑：feeder 级指标 → county 级格式指标 Map
    // ============================================================

    /**
     * 将 feeder 级指标列表按 metric_code 聚合，
     * 输出与 county 级指标同 key 的 Map（供 buildDashboardVO 使用）
     */
    private Map<String, String> aggregateFeederMetrics(List<StaticIndicatorMetric> feederMetrics) {
        // 按 metric_code 分组
        Map<String, List<StaticIndicatorMetric>> byCode = feederMetrics.stream()
                .collect(Collectors.groupingBy(StaticIndicatorMetric::getMetricCode));

        // 馈线总数（去重 feederId）
        long totalFeeders = feederMetrics.stream()
                .map(StaticIndicatorMetric::getFeederId)
                .filter(Objects::nonNull)
                .distinct()
                .count();

        Map<String, String> result = new HashMap<>();
        result.put("feeder_total_count", String.valueOf(totalFeeders));

        // 布尔计数类：count(true)
        for (Map.Entry<String, String> entry : BOOL_COUNT_MAP.entrySet()) {
            long count = countTrue(byCode.get(entry.getValue()));
            result.put(entry.getKey(), String.valueOf(count));
        }

        // 布尔比率类：count(true)/total×100
        for (Map.Entry<String, String> entry : BOOL_RATE_MAP.entrySet()) {
            long trueCount = countTrue(byCode.get(entry.getValue()));
            if (totalFeeders > 0) {
                BigDecimal rate = new BigDecimal(trueCount)
                        .divide(new BigDecimal(totalFeeders), 6, RoundingMode.HALF_UP)
                        .multiply(new BigDecimal("100"))
                        .setScale(2, RoundingMode.HALF_UP);
                result.put(entry.getKey(), rate.toPlainString());
            }
        }

        // 整数求和类
        for (Map.Entry<String, String> entry : INT_SUM_MAP.entrySet()) {
            int sum = sumInt(byCode.get(entry.getValue()));
            result.put(entry.getKey(), String.valueOf(sum));
        }

        // 特殊：tied_feeder_total_count = count(has_tie=true)
        result.put("tied_feeder_total_count", String.valueOf(countTrue(byCode.get("has_tie"))));

        // 特殊：standard_wiring_feeder_count = count(is_standard_wiring=true)
        result.put("standard_wiring_feeder_count",
                String.valueOf(countTrue(byCode.get("is_standard_wiring"))));

        // 特殊：connected_capacity_anomaly_count = 超标准条数 + 负荷组异常数
        int capacityAnomaly = Integer.parseInt(result.getOrDefault("connected_capacity_exceed_feeder_count", "0"))
                + Integer.parseInt(result.getOrDefault("load_group_capacity_anomaly_count", "0"));
        result.put("connected_capacity_anomaly_count", String.valueOf(capacityAnomaly));

        return result;
    }

    private long countTrue(List<StaticIndicatorMetric> metrics) {
        if (metrics == null) return 0;
        return metrics.stream()
                .filter(m -> "true".equalsIgnoreCase(m.getValue()))
                .count();
    }

    private int sumInt(List<StaticIndicatorMetric> metrics) {
        if (metrics == null) return 0;
        return metrics.stream()
                .filter(m -> StringUtils.isNotBlank(m.getValue()))
                .mapToInt(m -> {
                    try {
                        return new BigDecimal(m.getValue()).intValue();
                    } catch (NumberFormatException e) {
                        return 0;
                    }
                })
                .sum();
    }

    // ============================================================
    // 构建 VO（type=2 和 type=3/4 共用）
    // ============================================================

    private StaticGridDashboardVO buildDashboardVO(StaticIndicatorResult result,
                                                    Map<String, String> metricMap,
                                                    BigDecimal outageDuration) {
        return StaticGridDashboardVO.builder()
                .resultId(result.getId())
                .batchId(result.getBatchId())
                .countyId(result.getCountyId())
                .countySid(result.getCountySid())
                .countyName(result.getCountyName())
                .createTime(result.getCreateTime())
                .dataQualityStatus(result.getDataQualityStatus())
                .dataQualityCompletenessRate(result.getDataQualityCompletenessRate())
                // 一、标准化网架
                .wiringStandardizationRate(toBigDecimal(metricMap.get("wiring_standardization_rate")))
                .mainTrunkSectionStandardizationRate(toBigDecimal(metricMap.get("main_trunk_section_standardization_rate")))
                // 二、供电可靠性
                .outageDurationHoursHouseholds(outageDuration)
                .lineNMinus1PassRate(toBigDecimal(metricMap.get("n_minus_1_pass_rate")))
                .interSubstationNoConnectionCount(calcInterSubstationNoConnectionCount(
                        metricMap.get("feeder_total_count"),
                        metricMap.get("inter_substation_interconnection_rate")))
                .sameBusInterconnectionIssueCount(toInteger(metricMap.get("same_bus_interconnection_issue_count")))
                .excessiveTiePointFeederCount(toInteger(metricMap.get("excessive_tie_point_feeder_count")))
                .singleRadialFeederCount(toInteger(metricMap.get("single_radial_feeder_count")))
                .largeBranchFeederCount(toInteger(metricMap.get("large_branch_issue_feeder_count")))
                .unreasonableSegmentCount(toInteger(metricMap.get("unreasonable_segment_count_feeder_count")))
                .mainTrunkSegmentDenseCount(toInteger(metricMap.get("main_trunk_lantern_issue_feeder_count")))
                // 三、电压质量
                .iecUserVoltageIndex(null)  // 预留
                .supplyRadiusExceedFeederCount(toInteger(metricMap.get("supply_radius_exceed_feeder_count")))
                .extraLongFeederCount(toInteger(metricMap.get("extra_long_feeder_count")))
                // 四、供电能力
                .regionalMaxLoadRate(null)
                .regionalAvgLoadRate(null)
                .lineOverloadCount(null)
                .mainTrunkSectionMismatchCount(toInteger(metricMap.get("main_trunk_bottleneck_feeder_count")))
                .connectedCapacityExceedFeederCount(toInteger(metricMap.get("connected_capacity_exceed_feeder_count")))
                .loadGroupCapacityAnomalyCount(toInteger(metricMap.get("load_group_capacity_anomaly_count")))
                .comprehensiveLossRate(null)
                .powerFactorPassRate(null)
                .build();
    }

    // ============================================================
    // 主表查询辅助
    // ============================================================

    /**
     * 区县维度：按 maintOrgId + 月份查最新一条主表记录
     */
    private StaticIndicatorResult getLatestByMaintOrgId(String maintOrgId, YearMonth ym) {
        LocalDate monthStart = ym.atDay(1);
        LocalDate monthEnd = ym.atEndOfMonth();
        LambdaQueryWrapper<StaticIndicatorResult> wrapper = new LambdaQueryWrapper<StaticIndicatorResult>()
                .eq(StaticIndicatorResult::getMaintOrgId, maintOrgId)
                .ge(StaticIndicatorResult::getCreateTime, monthStart.atStartOfDay())
                .le(StaticIndicatorResult::getCreateTime, monthEnd.atTime(23, 59, 59))
                .orderByDesc(StaticIndicatorResult::getCreateTime)
                .last("LIMIT 1");
        return getOne(wrapper);
    }

    /**
     * 获取该月所有主表批次ID（type=3/4 用——先拿到月份范围内的 result_id 再查 metric）
     */
    private List<Long> getResultIdsByMonth(YearMonth ym) {
        LocalDate monthStart = ym.atDay(1);
        LocalDate monthEnd = ym.atEndOfMonth();
        LambdaQueryWrapper<StaticIndicatorResult> wrapper = new LambdaQueryWrapper<StaticIndicatorResult>()
                .ge(StaticIndicatorResult::getCreateTime, monthStart.atStartOfDay())
                .le(StaticIndicatorResult::getCreateTime, monthEnd.atTime(23, 59, 59));
        List<StaticIndicatorResult> results = list(wrapper);
        return results.stream()
                .map(StaticIndicatorResult::getId)
                .collect(Collectors.toList());
    }

    /**
     * 查 county 级或 feeder 级指标
     */
    private List<StaticIndicatorMetric> getMetrics(Long resultId, String level,
                                                    String feederId, String substationId) {
        LambdaQueryWrapper<StaticIndicatorMetric> wrapper = new LambdaQueryWrapper<StaticIndicatorMetric>()
                .eq(StaticIndicatorMetric::getResultId, resultId)
                .eq(StaticIndicatorMetric::getLevel, level);
        if (feederId != null) {
            wrapper.eq(StaticIndicatorMetric::getFeederId, feederId);
        }
        if (substationId != null) {
            wrapper.eq(StaticIndicatorMetric::getSourceSubstationId, substationId);
        }
        return metricMapper.selectList(wrapper);
    }

    private Map<String, String> metricsToMap(List<StaticIndicatorMetric> metrics) {
        Map<String, String> map = new HashMap<>();
        for (StaticIndicatorMetric m : metrics) {
            map.put(m.getMetricCode(), m.getValue());
        }
        return map;
    }

    // ============================================================
    // 工具方法
    // ============================================================

    /**
     * 解析 daytime（如 "2026-7-16"）为 YearMonth
     */
    private YearMonth parseYearMonth(String daytime) {
        if (StringUtils.isBlank(daytime)) {
            return YearMonth.now();
        }
        try {
            LocalDate date = LocalDate.parse(daytime, DateTimeFormatter.ofPattern("yyyy-M-d"));
            return YearMonth.from(date);
        } catch (DateTimeParseException e) {
            log.warn("daytime 格式非法: {}, 使用当前月份", daytime);
            return YearMonth.now();
        }
    }

    /**
     * 站间无联络线路数 = 馈线总数 × (1 - 站间联络率/100)
     */
    private Integer calcInterSubstationNoConnectionCount(String feederTotalCountStr, String interSubstationRateStr) {
        Integer total = toInteger(feederTotalCountStr);
        if (total == null || total == 0) return null;
        if (StringUtils.isBlank(interSubstationRateStr)) return total;
        try {
            BigDecimal rate = new BigDecimal(interSubstationRateStr);
            BigDecimal noConnRatio = BigDecimal.ONE.subtract(
                    rate.divide(new BigDecimal("100"), 6, RoundingMode.HALF_UP));
            return new BigDecimal(total).multiply(noConnRatio).setScale(0, RoundingMode.HALF_UP).intValue();
        } catch (NumberFormatException e) {
            return null;
        }
    }

    private BigDecimal toBigDecimal(String value) {
        if (StringUtils.isBlank(value)) return null;
        try {
            return new BigDecimal(value);
        } catch (NumberFormatException e) {
            return null;
        }
    }

    private Integer toInteger(String value) {
        if (StringUtils.isBlank(value)) return null;
        try {
            return Integer.valueOf(value);
        } catch (NumberFormatException e) {
            try {
                return new BigDecimal(value).intValue();
            } catch (NumberFormatException e2) {
                return null;
            }
        }
    }

    // ============================================================
    // 供电能力数据：从 capacity_daily 查区域/馈线负载率
    // ============================================================

    /**
     * 从 fhzg_se_capacity_daily 查询区域/馈线最大负载率、平均负载率、过载条数
     * 时间段：月初到昨天（当日数据尚未入日汇总表）
     */
    private void fillCapacityMetrics(StaticGridDashboardVO vo, String countyId,
                                      String subsId, String feederId, YearMonth ym) {
        LocalDate monthStart = ym.atDay(1);
        LocalDate monthEnd = ym.atEndOfMonth();
        LocalDate today = LocalDate.now();
        LocalDate endDate = monthEnd.isBefore(today) ? monthEnd : today.minusDays(1);

        // 按维度过滤
        LambdaQueryWrapper<FhzgSeCapacityDaily> wrapper = new LambdaQueryWrapper<FhzgSeCapacityDaily>()
                .ge(FhzgSeCapacityDaily::getStatDate, monthStart)
                .le(FhzgSeCapacityDaily::getStatDate, endDate);
        if (feederId != null) {
            wrapper.eq(FhzgSeCapacityDaily::getFeederId, feederId);
        } else if (subsId != null) {
            wrapper.eq(FhzgSeCapacityDaily::getSubsId, subsId);
        } else if (countyId != null) {
            wrapper.eq(FhzgSeCapacityDaily::getCountyId, countyId);
        }

        List<FhzgSeCapacityDaily> list = capacityDailyMapper.selectList(wrapper);
        if (list.isEmpty()) return;

        // 区域最大负载率
        BigDecimal maxLoad = list.stream()
                .map(FhzgSeCapacityDaily::getMaxLoadRate)
                .filter(Objects::nonNull)
                .max(BigDecimal::compareTo)
                .orElse(null);
        vo.setRegionalMaxLoadRate(maxLoad);

        // 区域平均负载率：对每日 avg_load_rate 取均值
        double avg = list.stream()
                .map(FhzgSeCapacityDaily::getAvgLoadRate)
                .filter(Objects::nonNull)
                .mapToDouble(BigDecimal::doubleValue)
                .average()
                .orElse(-1);
        if (avg >= 0) {
            vo.setRegionalAvgLoadRate(BigDecimal.valueOf(avg).setScale(2, RoundingMode.HALF_UP));
        }

        // 过载线路数
        if (feederId != null) {
            // 单馈线：该月有任意过载记录即 1
            boolean hasOverload = list.stream()
                    .anyMatch(d -> d.getOverloadCount() != null && d.getOverloadCount() > 0);
            vo.setLineOverloadCount(hasOverload ? 1 : 0);
        } else {
            // 区县/变电站：去重有过载记录的馈线数
            long count = list.stream()
                    .filter(d -> d.getOverloadCount() != null && d.getOverloadCount() > 0)
                    .map(FhzgSeCapacityDaily::getFeederId)
                    .distinct()
                    .count();
            if (count > 0) {
                vo.setLineOverloadCount((int) count);
            }
        }
    }
}
