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

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hdkj.lt.si.config.StaticGridThresholdProp;
import com.hdkj.lt.si.dao.StaticIndicatorMetricMapper;
import com.hdkj.lt.si.dao.StaticIndicatorResultMapper;
import com.hdkj.lt.si.dao.StaticProblemDetailMapper;
import com.hdkj.lt.si.entity.staticgrid.StaticIndicatorMetric;
import com.hdkj.lt.si.entity.staticgrid.StaticIndicatorResult;
import com.hdkj.lt.si.entity.staticgrid.StaticProblemDetail;
import com.hdkj.lt.si.service.remote.impl.AlgorithmRemoteCallServiceImpl;
import com.hdkj.lt.si.service.staticgrid.StaticIndicatorResultService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

/**
 * 静态网架评估结果服务实现
 * <p>
 * 调用算法接口获取完整 JSON，解析后写入 3 张表：
 * <ol>
 *   <li>t_static_indicator_result  — 主表（一次计算一行）</li>
 *   <li>t_static_indicator_metric  — 指标明细（county + feeder 两级扁平化）</li>
 *   <li>t_static_problem_detail     — 问题详情</li>
 * </ol>
 *
 * @author lsl
 * @since 2026-07-19
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class StaticIndicatorResultServiceImpl
        extends ServiceImpl<StaticIndicatorResultMapper, StaticIndicatorResult>
        implements StaticIndicatorResultService {

    private final StaticIndicatorMetricMapper metricMapper;
    private final StaticProblemDetailMapper problemDetailMapper;

    @Resource(type = AlgorithmRemoteCallServiceImpl.class)
    private AlgorithmRemoteCallServiceImpl algorithmRemoteCallService;

    @Resource
    private StaticGridThresholdProp staticGridThresholdProp;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long saveStaticGridResult(String batchId, String countyId, String countySid, String countyName, String topologyVersion) {
        // 1. 按新API格式构建请求体
        JSONObject requestBody = new JSONObject();
        JSONObject county = new JSONObject();
        county.put("county_id", countyId);
        county.put("county_sid", countySid != null ? countySid : countyId);
        county.put("county_name", countyName != null ? countyName : countyId);
        requestBody.put("county", county);
        requestBody.put("scope", "county");
        requestBody.put("topology_version", topologyVersion != null ? topologyVersion : "2026-07-01");
        requestBody.put("force_recalculate", Boolean.TRUE);
        // 算法判定阈值（未配置的字段沿用算法默认值，见 StaticGridThresholdProp）
        requestBody.put("algorithm_config", staticGridThresholdProp.toAlgorithmConfigMap());

        // 2. 调算法
        String rawResponse = algorithmRemoteCallService.queryStaticGridIndicators(requestBody.toJSONString());
        if (StringUtils.isBlank(rawResponse)) {
            log.warn("静态网架评估接口返回空 batchId={}, countyId={}", batchId, countyId);
            return null;
        }

        // 2. 解析顶层
        JSONObject root = JSON.parseObject(rawResponse);
        String responseType = root.getString("response_type");
        String requestId = root.getString("request_id");

        JSONObject countyBasicInfo = root.getJSONObject("county_basic_info");
        String respCountySid = countyBasicInfo != null ? countyBasicInfo.getString("county_sid") : null;
        String respCountyName = countyBasicInfo != null ? countyBasicInfo.getString("county_name") : null;
        JSONArray feederIdsArr = countyBasicInfo != null ? countyBasicInfo.getJSONArray("feeder_ids") : null;
        String feederIds = feederIdsArr != null ? String.join(",", feederIdsArr.toJavaList(String.class)) : null;

        JSONObject calcResult = root.getJSONObject("calculation_result");
        JSONObject countyResult = calcResult != null ? calcResult.getJSONObject("county_result") : null;

        JSONObject dataQuality = calcResult != null ? calcResult.getJSONObject("data_quality") : null;
        String dataQualityStatus = dataQuality != null ? dataQuality.getString("status") : null;
        BigDecimal completenessRate = dataQuality != null ? dataQuality.getBigDecimal("completeness_rate") : null;

        JSONObject processInfo = root.getJSONObject("process_info");
        String algorithm = processInfo != null ? processInfo.getString("algorithm") : null;
        BigDecimal durationSec = processInfo != null ? processInfo.getBigDecimal("duration_sec") : null;
        String status = processInfo != null ? processInfo.getString("status") : null;

        // 3. 写主表
        StaticIndicatorResult mainRecord = StaticIndicatorResult.builder()
                .batchId(batchId)
                .countyId(countyId)
                .maintOrgId(countyId)
                .countySid(countySid)
                .countyName(countyName)
                .feederIds(feederIds)
                .responseType(responseType)
                .requestId(requestId)
                .rawResponse(rawResponse)
                .algorithm(algorithm)
                .durationSec(durationSec)
                .status(status)
                .dataQualityStatus(dataQualityStatus)
                .dataQualityCompletenessRate(completenessRate)
                .createTime(LocalDateTime.now())
                .build();
        save(mainRecord);
        Long resultId = mainRecord.getId();

        // 4-5. 写指标明细 + 问题详情
        List<StaticIndicatorMetric> metricList = new ArrayList<>();
        List<StaticProblemDetail> problemDetailList = new ArrayList<>();

        // county 级
        if (countyResult != null) {
            JSONArray categories = countyResult.getJSONArray("categories");
            if (categories != null) {
                for (int i = 0; i < categories.size(); i++) {
                    JSONObject category = categories.getJSONObject(i);
                    parseCategoryMetrics(category, resultId, "county", null, null,
                            null, null, null, null, metricList, problemDetailList);
                }
            }
        }

        // feeder 级
        if (calcResult != null) {
            JSONArray feederResults = calcResult.getJSONArray("feeder_results");
            if (feederResults != null) {
                for (int i = 0; i < feederResults.size(); i++) {
                    JSONObject feeder = feederResults.getJSONObject(i);
                    String feederId = feeder.getString("feeder_id");
                    String feederName = feeder.getString("feeder_name");
                    String sourceSubstationId = feeder.getString("source_substation_id");
                    String sourceSubstationName = feeder.getString("source_substation_name");
                    String sourceBusId = feeder.getString("source_bus_id");
                    String supplyAreaType = feeder.getString("supply_area_type");
                    JSONArray feederCategories = feeder.getJSONArray("categories");
                    if (feederCategories != null) {
                        for (int j = 0; j < feederCategories.size(); j++) {
                            JSONObject category = feederCategories.getJSONObject(j);
                            parseCategoryMetrics(category, resultId, "feeder", feederId,
                                    feederName, sourceSubstationId, sourceSubstationName,
                                    sourceBusId, supplyAreaType,
                                    metricList, problemDetailList);
                        }
                    }
                }
            }
        }

        // 批量插入指标明细
        for (StaticIndicatorMetric m : metricList) {
            metricMapper.insert(m);
        }
        log.info("静态网架指标明细入库完成 resultId={}, metricCount={}", resultId, metricList.size());

        // 批量插入问题详情（从每个指标的 details[] 内嵌解析）
        for (StaticProblemDetail d : problemDetailList) {
            problemDetailMapper.insert(d);
        }
        log.info("静态网架问题详情入库完成 resultId={}, problemCount={}", resultId, problemDetailList.size());

        log.info("静态网架评估入库完成 batchId={}, countyId={}, resultId={}", batchId, countyId, resultId);
        return resultId;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long triggerManualStaticGrid(String countyId, String countySid, String countyName, String topologyVersion) {
        // 1. 删除该区县已有数据
        LambdaQueryWrapper<StaticIndicatorResult> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StaticIndicatorResult::getCountyId, countyId);
        List<StaticIndicatorResult> existing = baseMapper.selectList(wrapper);

        if (!existing.isEmpty()) {
            List<Long> resultIds = new ArrayList<>();
            for (StaticIndicatorResult r : existing) {
                resultIds.add(r.getId());
            }

            // 删除指标明细
            LambdaQueryWrapper<StaticIndicatorMetric> metricWrapper = new LambdaQueryWrapper<>();
            metricWrapper.in(StaticIndicatorMetric::getResultId, resultIds);
            int metricDel = metricMapper.delete(metricWrapper);

            // 删除问题详情
            LambdaQueryWrapper<StaticProblemDetail> problemWrapper = new LambdaQueryWrapper<>();
            problemWrapper.in(StaticProblemDetail::getResultId, resultIds);
            int problemDel = problemDetailMapper.delete(problemWrapper);

            // 删除主表
            int resultDel = baseMapper.delete(wrapper);

            log.info("手动触发：已删除区县旧记录 countyId={}, resultCount={}, metricCount={}, problemCount={}",
                    countyId, resultDel, metricDel, problemDel);
        }

        // 2. 生成批次ID
        String batchId = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS"));

        // 3. 调用标准的保存逻辑（调算法 + 插入）
        return saveStaticGridResult(batchId, countyId, countySid, countyName, topologyVersion);
    }

    /**
     * 解析一个 category 下的 metrics 数组，追加到 metricList
     */
    private void parseCategoryMetrics(JSONObject category, Long resultId, String level,
                                       String feederId, String feederName,
                                       String sourceSubstationId, String sourceSubstationName,
                                       String sourceBusId, String supplyAreaType,
                                       List<StaticIndicatorMetric> metricList,
                                       List<StaticProblemDetail> problemDetailList) {
        String categoryCode = category.getString("category_code");
        String categoryName = category.getString("category_name");
        JSONArray metrics = category.getJSONArray("metrics");
        if (metrics == null) {
            return;
        }
        for (int i = 0; i < metrics.size(); i++) {
            JSONObject m = metrics.getJSONObject(i);
            Object valueObj = m.get("value");
            String valueStr = valueObj == null ? null : String.valueOf(valueObj);

            StaticIndicatorMetric metric = StaticIndicatorMetric.builder()
                    .resultId(resultId)
                    .level(level)
                    .feederId(feederId)
                    .feederName(feederName)
                    .sourceSubstationId(sourceSubstationId)
                    .sourceSubstationName(sourceSubstationName)
                    .sourceBusId(sourceBusId)
                    .supplyAreaType(supplyAreaType)
                    .categoryCode(categoryCode)
                    .categoryName(categoryName)
                    .metricCode(m.getString("metric_code"))
                    .metricName(m.getString("metric_name"))
                    .value(valueStr)
                    .unit(m.getString("unit"))
                    .resultClass(m.getString("result_class"))
                    .severity(m.getString("severity"))
                    .calculationStatus(m.getString("calculation_status"))
                    .isProblem(m.getBoolean("is_problem") != null && m.getBoolean("is_problem") ? 1 : 0)
                    .build();
            metricList.add(metric);

            // 提取该指标下的 details[] → t_static_problem_detail
            JSONArray details = m.getJSONArray("details");
            if (details != null && !details.isEmpty()) {
                for (int j = 0; j < details.size(); j++) {
                    JSONObject d = details.getJSONObject(j);
                    JSONArray deviceIds = d.getJSONArray("device_ids");
                    String deviceIdsStr = deviceIds != null && !deviceIds.isEmpty()
                            ? JSON.toJSONString(deviceIds) : null;

                    StaticProblemDetail detail = StaticProblemDetail.builder()
                            .resultId(resultId)
                            .problemId(level + "_" + m.getString("metric_code") + "_" + j)
                            .feederId(feederId)
                            .categoryCode(categoryCode)
                            .categoryName(categoryName)
                            .metricCode(m.getString("metric_code"))
                            .metricName(m.getString("metric_name"))
                            .severity(m.getString("severity"))
                            .objectType("device")
                            .objectId(deviceIdsStr)
                            .actualValue(valueStr)
                            .description(d.getString("reason"))
                            .suggestion(d.getString("reason_code"))
                            .build();
                    problemDetailList.add(detail);
                }
            }
        }
    }
}
