{% extends "service_monitor/base.html" %}
{% block title %}监测统计{% endblock %}

{% block extra_css %}
<style>
    .filter-bar {
        display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
        margin-bottom: 20px; padding: 16px;
        background: #fff; border-radius: 12px; border: 1px solid var(--gray-200);
    }
    .filter-group { display: flex; align-items: center; gap: 8px; }
    .filter-label { font-size: 14px; color: var(--gray-700); font-weight: 500; }
    .filter-select, .filter-date {
        padding: 8px 12px; border: 1px solid var(--gray-200);
        border-radius: 6px; font-size: 14px; background: #fff;
    }
    .btn-query {
        background: var(--primary); color: #fff; border: none;
        padding: 8px 20px; border-radius: 6px; font-size: 14px;
        font-weight: 600; cursor: pointer;
    }
    .btn-query:hover { background: var(--primary-hover); }

    .overview-cards {
        display: grid; grid-template-columns: repeat(4,1fr);
        gap: 12px; margin-bottom: 24px;
    }
    .ov-card {
        background: #fff; border-radius: 12px; padding: 18px;
        text-align: center; border: 1px solid var(--gray-200);
    }
    .ov-card .value { font-size: 28px; font-weight: 700; color: var(--gray-900); }
    .ov-card .label { font-size: 13px; color: var(--gray-500); margin-top: 4px; }
    .ov-card.highlight .value { color: var(--primary); }
    .ov-card.warn .value { color: var(--yellow); }
    .ov-card.crit .value { color: var(--red); }

    .chart-section {
        background: #fff; border-radius: 12px; border: 1px solid var(--gray-200);
        margin-bottom: 20px; padding: 20px;
    }
    .chart-title {
        font-size: 16px; font-weight: 700; color: var(--gray-900);
        margin-bottom: 16px; display: flex; align-items: center; gap: 8px;
    }
    .chart-container { width: 100%; min-height: 350px; }

    .trend-layout { display: flex; gap: 20px; }
    .trend-left { flex: 2; min-width: 0; }
    .trend-right { flex: 1; min-width: 0; }

    .item-selector {
        padding: 8px 12px; border: 1px solid var(--gray-200);
        border-radius: 6px; font-size: 14px; background: #fff;
        max-width: 300px; width: 100%;
    }

    .empty-state {
        text-align: center; padding: 40px; color: var(--gray-500); font-size: 14px;
    }

    @media screen and (max-width: 768px) {
        .filter-bar { gap: 10px; padding: 12px; flex-direction: column; align-items: stretch; }
        .filter-group { width: 100%; }
        .filter-label { font-size: 13px; }
        .filter-select, .filter-date { padding: 6px 10px; font-size: 13px; width: 100%; }
        .btn-query { padding: 6px 14px; font-size: 13px; width: 100%; }
        .overview-cards { grid-template-columns: repeat(2, 1fr); gap: 8px; }
        .ov-card { padding: 12px; }
        .ov-card .value { font-size: 22px; }
        .ov-card .label { font-size: 12px; }
        .trend-layout { flex-direction: column; }
        .chart-section { padding: 14px; margin-bottom: 14px; }
        .chart-title { font-size: 14px; margin-bottom: 12px; }
        .chart-container { min-height: 250px; }
        .item-selector { max-width: 100%; font-size: 13px; }
        .trend-filters { flex-direction: column; gap: 10px; }
        .trend-filters .filter-group { width: 100%; }
        .trend-filters .filter-select { width: 100%; min-width: 0; }
    }
    @media screen and (max-width: 480px) {
        .filter-bar { padding: 10px; gap: 8px; }
        .filter-select, .filter-date { padding: 5px 8px; font-size: 12px; }
        .btn-query { padding: 5px 12px; font-size: 12px; }
        .overview-cards { grid-template-columns: 1fr 1fr; gap: 6px; }
        .ov-card { padding: 10px; }
        .ov-card .value { font-size: 18px; }
        .ov-card .label { font-size: 11px; }
        .chart-section { padding: 10px; }
        .chart-container { min-height: 200px; }
        .chart-title { font-size: 13px; }
    }
</style>
{% endblock %}

{% block content %}
<div class="container">
    <!-- 筛选栏 -->
    <div class="filter-bar">
        <div class="filter-group">
            <span class="filter-label">目标服务器</span>
            <select id="filterTarget" class="filter-select">
                <option value="">全部目标</option>
                {% for t in targets %}
                <option value="{{ t.id }}">{{ t.name }}</option>
                {% endfor %}
            </select>
        </div>
        <div class="filter-group">
            <span class="filter-label">开始日期</span>
            <input type="date" id="filterStart" class="filter-date">
        </div>
        <div class="filter-group">
            <span class="filter-label">结束日期</span>
            <input type="date" id="filterEnd" class="filter-date">
        </div>
        <button class="btn-query" onclick="fetchAllData()">🔍 查询</button>
    </div>

    <!-- 概览卡片 -->
    <div class="overview-cards">
        <div class="ov-card"><div class="value" id="ovReports">-</div><div class="label">总报告数</div></div>
        <div class="ov-card warn"><div class="value" id="ovAbnormalRate">-</div><div class="label">异常率</div></div>
        <div class="ov-card crit"><div class="value" id="ovTopItem">-</div><div class="label">最常异常项</div></div>
        <div class="ov-card highlight"><div class="value" id="ovAvgItems">-</div><div class="label">平均检测项/报告</div></div>
    </div>

    <!-- 模块健康概览 -->
    <div class="chart-section">
        <div class="chart-title">🧩 模块健康概览</div>
        <div class="chart-container" id="chartModules"></div>
    </div>

    <!-- 检测项趋势分析 -->
    <div class="chart-section">
        <div class="chart-title">
            📉 检测项趋势分析
        </div>
        <div class="trend-filters" style="margin-bottom:16px; display:flex; gap:16px; flex-wrap:wrap; align-items:center;">
            <div class="filter-group">
                <span class="filter-label" style="font-size:14px; color:var(--gray-700); font-weight:500;">模块</span>
                <select id="moduleSelector" class="filter-select" onchange="onModuleChange()" style="min-width:160px;">
                    <option value="">-- 选择模块 --</option>
                </select>
            </div>
            <div class="filter-group">
                <span class="filter-label" style="font-size:14px; color:var(--gray-700); font-weight:500;">检测项</span>
                <select id="itemSelector" class="filter-select" onchange="fetchItemTrend()" style="min-width:200px;" disabled>
                    <option value="">-- 请先选择模块 --</option>
                </select>
            </div>
        </div>
        <div class="trend-layout">
            <div class="trend-left">
                <div class="chart-container" id="chartTrendLine" style="min-height:300px;"></div>
            </div>
            <div class="trend-right">
                <div class="chart-container" id="chartTrendPie" style="min-height:300px;"></div>
            </div>
        </div>
    </div>

    <!-- 高频异常检测项 -->
    <div class="chart-section">
        <div class="chart-title">🚨 高频异常检测项 TOP 10</div>
        <div class="chart-container" id="chartAbnormal"></div>
    </div>
</div>
{% endblock %}

{% block extra_js %}
<script src="https://cdn.jsdelivr.net/npm/echarts@5.5.1/dist/echarts.min.js"></script>
<script>
const COLORS = { normal: '#16a34a', warning: '#d97706', critical: '#dc2626', primary: '#2563eb' };
let chartModules, chartTrendLine, chartTrendPie, chartAbnormal;
let cachedModulesData = null;  // 缓存模块数据用于二级联动

// 初始化日期默认值（近 30 天）
function initDates() {
    const today = new Date();
    const start = new Date(today);
    start.setDate(start.getDate() - 30);
    document.getElementById('filterEnd').value = today.toISOString().slice(0, 10);
    document.getElementById('filterStart').value = start.toISOString().slice(0, 10);
}

function getFilters() {
    return {
        target_id: document.getElementById('filterTarget').value,
        start_date: document.getElementById('filterStart').value,
        end_date: document.getElementById('filterEnd').value,
    };
}

function buildParams(extra) {
    const f = getFilters();
    const p = new URLSearchParams();
    if (f.target_id) p.set('target_id', f.target_id);
    if (f.start_date) p.set('start_date', f.start_date);
    if (f.end_date) p.set('end_date', f.end_date);
    if (extra) Object.entries(extra).forEach(([k,v]) => { if (v) p.set(k, v); });
    return p;
}

// 初始化 ECharts
function initCharts() {
    chartModules = echarts.init(document.getElementById('chartModules'));
    chartTrendLine = echarts.init(document.getElementById('chartTrendLine'));
    chartTrendPie = echarts.init(document.getElementById('chartTrendPie'));
    chartAbnormal = echarts.init(document.getElementById('chartAbnormal'));

    window.addEventListener('resize', () => {
        chartModules.resize();
        chartTrendLine.resize();
        chartTrendPie.resize();
        chartAbnormal.resize();
    });
}

// 概览
async function fetchOverview() {
    try {
        const r = await fetch('/api/service-monitor/statistics/overview?' + buildParams());
        const d = await r.json();
        if (!d.success) return;
        const data = d.data;

        document.getElementById('ovReports').textContent = data.total_reports;
        document.getElementById('ovAbnormalRate').textContent = data.abnormal_rate + '%';
        document.getElementById('ovTopItem').textContent = data.most_abnormal_item
            ? data.most_abnormal_item.name + ' (' + data.most_abnormal_item.abnormal_count + '次)'
            : '-';
        document.getElementById('ovAvgItems').textContent = data.total_reports > 0
            ? Math.round(data.total_items / data.total_reports)
            : '-';
    } catch (e) { console.error('fetchOverview error:', e); }
}

// 模块健康
async function fetchModules() {
    try {
        const r = await fetch('/api/service-monitor/statistics/modules?' + buildParams());
        const d = await r.json();
        if (!d.success) return;
        const modules = d.data.modules;
        if (!modules.length) {
            chartModules.setOption({ title: { text: '暂无数据', left: 'center', top: 'center', textStyle: { color: '#9ca3af', fontSize: 14 } } });
            return;
        }

        const names = modules.map(m => m.name);
        chartModules.setOption({
            tooltip: { trigger: 'axis', axisPointer: { type: 'shadow' },
                formatter: function(params) {
                    let s = params[0].name + '<br/>';
                    let total = 0, normal = 0;
                    params.forEach(p => { total += p.value; if (p.seriesName === '正常') normal += p.value; });
                    params.forEach(p => { s += p.marker + p.seriesName + ': ' + p.value + '<br/>'; });
                    s += '通过率: ' + (total > 0 ? (normal / total * 100).toFixed(1) : 0) + '%';
                    return s;
                }
            },
            legend: { data: ['正常', '警告', '严重'], bottom: 0 },
            grid: { left: 10, right: 20, bottom: 50, top: 20, containLabel: true },
            xAxis: { type: 'category', data: names, axisLabel: { rotate: 30, fontSize: 11 } },
            yAxis: { type: 'value' },
            series: [
                { name: '正常', type: 'bar', stack: 'total', data: modules.map(m => m.normal), itemStyle: { color: COLORS.normal } },
                { name: '警告', type: 'bar', stack: 'total', data: modules.map(m => m.warning), itemStyle: { color: COLORS.warning } },
                { name: '严重', type: 'bar', stack: 'total', data: modules.map(m => m.critical), itemStyle: { color: COLORS.critical } },
            ],
        });
    } catch (e) { console.error('fetchModules error:', e); }
}

// 模块和检测项数据
async function fetchItemKeys() {
    try {
        const r = await fetch('/api/service-monitor/statistics/item-keys?' + buildParams());
        const d = await r.json();
        if (!d.success) return;

        // 缓存数据用于二级联动
        cachedModulesData = d.data;

        // 填充模块选择器
        const modSel = document.getElementById('moduleSelector');
        const currentMod = modSel.value;
        modSel.innerHTML = '<option value="">-- 选择模块 --</option>';

        let currentCategory = '';
        d.data.forEach(group => {
            // 类别分隔标题
            if (group.category !== currentCategory) {
                currentCategory = group.category;
                const catLabel = currentCategory === 'system' ? '── 系统检测 ──' : '── 服务检测 ──';
                const catOpt = document.createElement('option');
                catOpt.disabled = true;
                catOpt.textContent = catLabel;
                catOpt.style.fontWeight = 'bold';
                catOpt.style.color = '#6b7280';
                catOpt.style.background = '#f3f4f6';
                modSel.appendChild(catOpt);
            }
            // 模块选项
            const opt = document.createElement('option');
            opt.value = group.module_id;
            opt.textContent = group.module_name;
            opt.dataset.category = group.category;
            modSel.appendChild(opt);
        });

        // 恢复选择状态
        if (currentMod && modSel.querySelector('option[value="' + currentMod + '"]')) {
            modSel.value = currentMod;
            onModuleChange();
        } else {
            // 重置检测项选择器
            const itemSel = document.getElementById('itemSelector');
            itemSel.innerHTML = '<option value="">-- 请先选择模块 --</option>';
            itemSel.disabled = true;
        }
    } catch (e) { console.error('fetchItemKeys error:', e); }
}

// 模块选择变化时，更新检测项选择器
function onModuleChange() {
    const modSel = document.getElementById('moduleSelector');
    const itemSel = document.getElementById('itemSelector');
    const moduleId = modSel.value;

    // 重置检测项选择器
    itemSel.innerHTML = '<option value="">-- 选择检测项 --</option>';

    if (!moduleId) {
        itemSel.disabled = true;
        return;
    }

    itemSel.disabled = false;

    // 从缓存中找到对应模块的检测项
    if (!cachedModulesData) return;
    const group = cachedModulesData.find(g => g.module_id === moduleId);
    if (!group || !group.items) return;

    // 填充检测项选择器
    group.items.forEach(item => {
        const opt = document.createElement('option');
        opt.value = item.key;
        // 状态类检测项标注 "(状态)" 后缀
        opt.textContent = item.name + (item.has_numeric ? '' : ' (状态)');
        itemSel.appendChild(opt);
    });
}

// 检测项趋势
async function fetchItemTrend(itemKey) {
    const key = itemKey || document.getElementById('itemSelector').value;
    if (!key) {
        chartTrendLine.clear();
        chartTrendPie.clear();
        return;
    }
    try {
        const r = await fetch('/api/service-monitor/statistics/item-trend?' + buildParams({ item_key: key }));
        const d = await r.json();
        if (!d.success) return;
        const data = d.data;
        const points = data.data_points || [];
        const numericCount = points.filter(p => p.value_num !== null).length;

        // 情况1：无数据点
        if (points.length === 0) {
            chartTrendLine.setOption({
                title: { text: '该检测项暂无数据', left: 'center', top: 'center',
                         textStyle: { color: '#9ca3af', fontSize: 14 } }
            }, true);
            chartTrendPie.setOption({
                title: { text: '暂无数据', left: 'center', top: 'center',
                         textStyle: { color: '#9ca3af', fontSize: 14 } }
            }, true);
            return;
        }

        // 情况2：有数据点但无数值（状态类/文本类）
        if (numericCount === 0) {
            chartTrendLine.setOption({
                title: {
                    text: '该检测项为状态/文本类型',
                    subtext: '无法绘制数值趋势图，请查看右侧状态分布',
                    left: 'center', top: 'center',
                    textStyle: { color: '#6b7280', fontSize: 14 },
                    subtextStyle: { color: '#9ca3af', fontSize: 12 }
                }
            }, true);

            // 饼图仍然显示状态分布
            const dist = data.status_distribution;
            const pieData = [
                { value: dist['正常'] || 0, name: '正常', itemStyle: { color: COLORS.normal } },
                { value: dist['警告'] || 0, name: '警告', itemStyle: { color: COLORS.warning } },
                { value: dist['严重'] || 0, name: '严重', itemStyle: { color: COLORS.critical } },
            ].filter(d => d.value > 0);

            if (pieData.length > 0) {
                chartTrendPie.setOption({
                    tooltip: { trigger: 'item', formatter: '{b}: {c} ({d}%)' },
                    legend: { bottom: 0 },
                    series: [{
                        type: 'pie', radius: ['40%', '70%'],
                        label: { formatter: '{b}\n{d}%' },
                        data: pieData,
                    }],
                }, true);
            } else {
                chartTrendPie.setOption({
                    title: { text: '暂无状态数据', left: 'center', top: 'center',
                             textStyle: { color: '#9ca3af', fontSize: 14 } }
                }, true);
            }
            return;
        }

        // 情况3：有数值数据，正常渲染折线图
        const times = points.map(p => p.time ? p.time.replace('T', ' ').slice(0, 16) : '');
        const values = points.map(p => p.value_num);

        // 按状态着色的散点
        const normalPts = [], warnPts = [], critPts = [];
        points.forEach((p, i) => {
            if (p.value_num == null) return;
            const pt = [i, p.value_num];
            if (p.status === '严重') critPts.push(pt);
            else if (p.status === '警告') warnPts.push(pt);
            else normalPts.push(pt);
        });

        const series = [
            { name: data.item_name, type: 'line', data: values, lineStyle: { color: COLORS.primary, width: 2 },
              itemStyle: { color: COLORS.primary }, symbol: 'circle', symbolSize: 6 },
            { name: '正常', type: 'scatter', data: normalPts, symbolSize: 8, itemStyle: { color: COLORS.normal } },
            { name: '警告', type: 'scatter', data: warnPts, symbolSize: 10, itemStyle: { color: COLORS.warning }, symbol: 'triangle' },
            { name: '严重', type: 'scatter', data: critPts, symbolSize: 10, itemStyle: { color: COLORS.critical }, symbol: 'diamond' },
        ];

        // 阈值参考线
        if (data.threshold) {
            const match = data.threshold.match(/([<>]=?)\s*([\d.]+)/);
            if (match) {
                const tv = parseFloat(match[2]);
                series.push({
                    name: '阈值', type: 'line', data: new Array(times.length).fill(tv),
                    lineStyle: { color: COLORS.critical, type: 'dashed', width: 1 }, symbol: 'none',
                    markLine: { data: [{ yAxis: tv, name: '阈值: ' + tv }], lineStyle: { color: COLORS.critical, type: 'dashed' }, label: { formatter: '阈值: ' + tv } }
                });
            }
        }

        chartTrendLine.setOption({
            tooltip: { trigger: 'axis',
                formatter: function(params) {
                    const idx = params[0].dataIndex;
                    const p = points[idx];
                    if (!p) return '';
                    let s = p.time ? p.time.replace('T', ' ').slice(0, 16) : '' + '<br/>';
                    s += '值: ' + p.value_raw + '<br/>';
                    s += '状态: ' + p.status;
                    return s;
                }
            },
            legend: { data: series.map(s => s.name).filter(n => n !== data.item_name || true), bottom: 0 },
            grid: { left: 10, right: 20, bottom: 40, top: 20, containLabel: true },
            xAxis: { type: 'category', data: times, axisLabel: { rotate: 30, fontSize: 10 } },
            yAxis: { type: 'value', name: data.unit || '' },
            series: series,
        }, true);

        // 饼图
        const dist = data.status_distribution;
        chartTrendPie.setOption({
            tooltip: { trigger: 'item', formatter: '{b}: {c} ({d}%)' },
            legend: { bottom: 0 },
            series: [{
                type: 'pie', radius: ['40%', '70%'],
                label: { formatter: '{b}\n{d}%' },
                data: [
                    { value: dist['正常'] || 0, name: '正常', itemStyle: { color: COLORS.normal } },
                    { value: dist['警告'] || 0, name: '警告', itemStyle: { color: COLORS.warning } },
                    { value: dist['严重'] || 0, name: '严重', itemStyle: { color: COLORS.critical } },
                ].filter(d => d.value > 0),
            }],
        }, true);

    } catch (e) { console.error('fetchItemTrend error:', e); }
}

// 高频异常项
async function fetchAbnormalItems() {
    try {
        const r = await fetch('/api/service-monitor/statistics/abnormal-items?' + buildParams());
        const d = await r.json();
        if (!d.success) return;
        const items = d.data.items;
        if (!items.length) {
            chartAbnormal.setOption({ title: { text: '暂无异常数据', left: 'center', top: 'center', textStyle: { color: '#9ca3af', fontSize: 14 } } });
            return;
        }

        const names = items.map(i => i.name).reverse();
        const warns = items.map(i => i.warning_count).reverse();
        const crits = items.map(i => i.critical_count).reverse();

        chartAbnormal.setOption({
            tooltip: { trigger: 'axis', axisPointer: { type: 'shadow' },
                formatter: function(params) {
                    const idx = params[0].dataIndex;
                    const item = items.slice().reverse()[idx];
                    let s = item.name + '<br/>';
                    s += '模块: ' + item.module_name + '<br/>';
                    s += '总出现: ' + item.total_appearances + ' 次<br/>';
                    s += '异常率: ' + item.abnormal_rate + '%<br/>';
                    params.forEach(p => { s += p.marker + p.seriesName + ': ' + p.value + '<br/>'; });
                    return s;
                }
            },
            legend: { data: ['警告', '严重'], bottom: 0 },
            grid: { left: 10, right: 20, bottom: 40, top: 20, containLabel: true },
            xAxis: { type: 'value' },
            yAxis: { type: 'category', data: names, axisLabel: { fontSize: 11, width: 120, overflow: 'truncate' } },
            series: [
                { name: '警告', type: 'bar', stack: 'total', data: warns, itemStyle: { color: COLORS.warning } },
                { name: '严重', type: 'bar', stack: 'total', data: crits, itemStyle: { color: COLORS.critical } },
            ],
        });
    } catch (e) { console.error('fetchAbnormalItems error:', e); }
}

// 全部数据
async function fetchAllData() {
    const btn = document.querySelector('.btn-query');
    btn.disabled = true;
    btn.textContent = '⏳ 查询中...';

    await Promise.all([
        fetchOverview(),
        fetchModules(),
        fetchItemKeys(),
        fetchAbnormalItems(),
    ]);

    // 如果检测项选择器有值，刷新趋势
    const sel = document.getElementById('itemSelector');
    if (sel.value) await fetchItemTrend();

    btn.disabled = false;
    btn.textContent = '🔍 查询';
}

// 点击异常项自动填充趋势
document.addEventListener('click', function(e) {
    // 通过 ECharts 事件处理
});

// 初始化
document.addEventListener('DOMContentLoaded', function() {
    initDates();
    initCharts();
    fetchAllData();

    // 异常项点击 → 自动选择检测项
    chartAbnormal.getZr().on('click', function(params) {
        const point = chartAbnormal.convertFromPixel({ seriesIndex: 0 }, [params.offsetX, params.offsetY]);
        if (point && point[1] !== undefined) {
            const idx = Math.round(point[1]);
            const items = chartAbnormal.getOption().yAxis[0].data;
            if (idx >= 0 && idx < items.length) {
                const itemName = items[idx];
                // 在缓存数据中查找对应的模块和检测项
                if (cachedModulesData) {
                    for (const group of cachedModulesData) {
                        for (const item of group.items) {
                            if (item.name === itemName) {
                                // 设置模块选择器
                                const modSel = document.getElementById('moduleSelector');
                                modSel.value = group.module_id;
                                onModuleChange();
                                // 设置检测项选择器
                                const itemSel = document.getElementById('itemSelector');
                                itemSel.value = item.key;
                                fetchItemTrend();
                                return;
                            }
                        }
                    }
                }
            }
        }
    });
});
</script>
{% endblock %}
