{% extends "service_monitor/base.html" %}
{% block title %}巡检执行{% endblock %}
{% set no_footer = true %}

{% block extra_css %}
<style>
    .run-card { background: #fff; border-radius: 14px; box-shadow: 0 2px 8px rgba(0,0,0,.06); border: 1px solid var(--gray-200); padding: 26px; max-width: 720px; }
    .run-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 20px; }
    .run-title { font-size: 18px; font-weight: 700; color: var(--gray-900); }
    .run-title .suite-tag { font-size: 13px; font-weight: 600; padding: 3px 10px; border-radius: 6px; margin-left: 8px; background: #eef2ff; color: var(--primary); }
    .btn-cancel { background: #fee2e2; color: var(--red); border: none; padding: 8px 16px; border-radius: 8px; font-size: 14px; font-weight: 600; cursor: pointer; }
    .btn-cancel:disabled { opacity: .4; cursor: not-allowed; }

    /* 进度条 */
    .progress-wrap { margin-bottom: 6px; }
    .progress-bar { height: 12px; background: var(--gray-100); border-radius: 6px; overflow: hidden; }
    .progress-fill { height: 100%; background: linear-gradient(90deg, var(--primary), #60a5fa); width: 0%; transition: width .3s; }
    .progress-text { display: flex; justify-content: space-between; font-size: 13px; color: var(--gray-500); margin-top: 8px; }

    /* 模块清单 */
    .module-list { margin-top: 20px; }
    .module-item { display: flex; align-items: center; gap: 12px; padding: 12px 0; border-bottom: 1px solid var(--gray-100); }
    .module-item:last-child { border-bottom: none; }
    .module-status { font-size: 18px; width: 24px; text-align: center; }
    .module-name { flex: 1; font-size: 15px; color: var(--gray-700); }
    .module-info { font-size: 13px; color: var(--gray-500); }
    .st-pending .module-name { color: var(--gray-400); }
    .st-running .module-name { color: var(--primary); font-weight: 600; }
    .st-done .module-name { color: var(--gray-900); }
    .sm-ok { color: var(--green); } .sm-warn { color: var(--yellow); } .sm-crit { color: var(--red); }

    .spinner { display: inline-block; width: 16px; height: 16px; border: 2px solid var(--gray-200); border-top-color: var(--primary); border-radius: 50%; animation: spin .8s linear infinite; }
    @keyframes spin { to { transform: rotate(360deg); } }

    .done-banner { display: none; text-align: center; padding: 20px; margin-top: 10px; border-radius: 10px; }
    .done-banner.show { display: block; }
    .done-ok { background: #dcfce7; color: #15803d; }
    .done-err { background: #fee2e2; color: var(--red); }
    .btn-report { display: inline-block; margin-top: 12px; background: var(--primary); color: #fff; padding: 9px 22px; border-radius: 8px; font-size: 14px; font-weight: 600; text-decoration: none; }

    @media screen and (max-width: 768px) {
        .run-card { padding: 16px; border-radius: 12px; }
        .run-head { flex-direction: column; align-items: flex-start; gap: 10px; }
        .run-title { font-size: 15px; }
        .run-title .suite-tag { font-size: 12px; padding: 2px 8px; }
        .btn-cancel { width: 100%; padding: 8px; }
        .progress-text { flex-direction: column; gap: 2px; font-size: 12px; }
        .module-item { gap: 8px; padding: 10px 0; }
        .module-status { font-size: 16px; width: 20px; }
        .module-name { font-size: 13px; }
        .module-info { font-size: 11px; }
        .btn-report { padding: 8px 18px; font-size: 13px; }
        .progress-bar { height: 10px; }
    }
    @media screen and (max-width: 480px) {
        .run-card { padding: 14px; border-radius: 10px; }
        .run-title { font-size: 14px; }
        .run-title .suite-tag { font-size: 11px; padding: 2px 6px; margin-left: 6px; }
        .progress-bar { height: 8px; }
        .progress-text { font-size: 11px; }
        .module-item { gap: 6px; padding: 8px 0; }
        .module-status { font-size: 14px; width: 18px; }
        .module-name { font-size: 12px; }
        .module-info { font-size: 10px; }
        .btn-report { padding: 7px 16px; font-size: 12px; }
        .done-banner { padding: 16px; font-size: 13px; }
        #done-text { word-break: break-word; }
    }
</style>
{% endblock %}

{% block content %}
<div class="run-card">
    <div class="run-head">
        <div class="run-title">
            {{ '🖥️' if target.type == 'local' else '🌐' }} {{ target.name }}
            <span class="suite-tag">{{ '⚡ 快速巡检' if suite == 'quick' else '🔍 全量巡检' }}</span>
        </div>
        <button class="btn-cancel" id="btn-cancel" onclick="cancelRun()">取消</button>
    </div>

    <div class="progress-wrap">
        <div class="progress-bar"><div class="progress-fill" id="progress-fill"></div></div>
        <div class="progress-text">
            <span id="progress-current">准备中...</span>
            <span id="progress-count">0 / 0</span>
        </div>
    </div>

    <div class="module-list" id="module-list"></div>

    <div class="done-banner" id="done-banner">
        <div id="done-text"></div>
        <a href="#" class="btn-report" id="btn-report" style="display:none;">查看报告 →</a>
    </div>
</div>
{% endblock %}

{% block extra_js %}
<script>
    const TARGET_ID = "{{ target.id }}";
    const SUITE = "{{ suite }}";
    let currentRunId = null;
    let evtSource = null;
    const moduleEls = {};

    function statusIcon(st) {
        if (st === 'done') return '✓';
        if (st === 'running') return '<span class="spinner"></span>';
        return '○';
    }

    function ensureModuleEl(name) {
        if (moduleEls[name]) return moduleEls[name];
        const div = document.createElement('div');
        div.className = 'module-item st-pending';
        div.innerHTML = `<span class="module-status">○</span><span class="module-name">${name}</span><span class="module-info"></span>`;
        document.getElementById('module-list').appendChild(div);
        moduleEls[name] = div;
        return div;
    }

    function setModuleStatus(name, st, info) {
        const el = ensureModuleEl(name);
        el.className = 'module-item st-' + st;
        el.querySelector('.module-status').innerHTML = statusIcon(st);
        if (info !== undefined) el.querySelector('.module-info').innerHTML = info;
    }

    function startInspection() {
        const url = `/api/service-monitor/run/stream?target_id=${encodeURIComponent(TARGET_ID)}&suite=${encodeURIComponent(SUITE)}`;
        evtSource = new EventSource(url);

        evtSource.onmessage = (e) => {
            let evt;
            try { evt = JSON.parse(e.data); } catch(_) { return; }
            if (evt.run_id) currentRunId = evt.run_id;

            if (evt.event === 'progress') {
                document.getElementById('progress-current').textContent = evt.current || '巡检中...';
                if (evt.total) {
                    const pct = Math.round((evt.done / evt.total) * 100);
                    document.getElementById('progress-fill').style.width = pct + '%';
                    document.getElementById('progress-count').textContent = `${evt.done} / ${evt.total}`;
                }
                if (evt.current && !evt.current.includes('...') && !evt.current.includes('测试') && !evt.current.includes('上传')) {
                    setModuleStatus(evt.current, 'running');
                }
            } else if (evt.event === 'module_done') {
                const s = evt.summary || {};
                let info = `${evt.items_count}项`;
                const parts = [];
                if (s['正常']) parts.push(`<span class="sm-ok">✓${s['正常']}</span>`);
                if (s['警告']) parts.push(`<span class="sm-warn">⚠${s['警告']}</span>`);
                if (s['严重']) parts.push(`<span class="sm-crit">✗${s['严重']}</span>`);
                info += ' ' + parts.join(' ');
                setModuleStatus(evt.module, 'done', info);
            } else if (evt.event === 'finished') {
                finishRun(true, evt.report_id, evt.summary);
            } else if (evt.event === 'error') {
                finishRun(false, null, null, evt.message);
            } else if (evt.event === 'cancelled') {
                finishRun(false, null, null, '巡检已取消');
            }
        };

        evtSource.onerror = () => {
            if (evtSource) { evtSource.close(); evtSource = null; }
        };
    }

    function finishRun(ok, reportId, summary, errMsg) {
        if (evtSource) { evtSource.close(); evtSource = null; }
        document.getElementById('btn-cancel').disabled = true;
        const banner = document.getElementById('done-banner');
        const text = document.getElementById('done-text');
        banner.classList.add('show');
        if (ok) {
            document.getElementById('progress-fill').style.width = '100%';
            document.getElementById('progress-current').textContent = '巡检完成';
            banner.className = 'done-banner show done-ok';
            const s = summary || {};
            text.innerHTML = `✅ 巡检完成：正常 ${s['正常']||0}，警告 ${s['警告']||0}，严重 ${s['严重']||0}`;
            if (reportId) {
                const btn = document.getElementById('btn-report');
                btn.href = '/service-monitor/report/' + reportId;
                btn.style.display = 'inline-block';
                setTimeout(() => { window.location.href = btn.href; }, 1500);
            }
        } else {
            banner.className = 'done-banner show done-err';
            text.textContent = '❌ ' + (errMsg || '巡检失败');
        }
    }

    /* 显示“已有巡检正在运行”的占位状态（不触发新巡检） */
    function showAlreadyRunning(runId, done, total) {
        currentRunId = runId;
        if (total) {
            const pct = Math.round((done / total) * 100);
            document.getElementById('progress-fill').style.width = pct + '%';
            document.getElementById('progress-count').textContent = `${done} / ${total}`;
        }
        document.getElementById('progress-current').textContent = '该目标已有巡检正在运行，请等待完成或取消后重试';
        const banner = document.getElementById('done-banner');
        const text = document.getElementById('done-text');
        banner.classList.add('show');
        banner.className = 'done-banner show done-err';
        text.textContent = `⚠️ 该目标已有巡检正在运行${total ? `（${done}/${total}）` : ''}，可点击右上角“取消”终止已有巡检后再重试`;
    }

    async function checkAndStart() {
        try {
            const resp = await fetch(`/api/service-monitor/run/status/${encodeURIComponent(TARGET_ID)}`, {credentials:'include'});
            if (resp.ok) {
                const status = await resp.json();
                if (status.running) {
                    showAlreadyRunning(status.run_id, status.done || 0, status.total || 0);
                    return;
                }
            }
        } catch(e) { /* 查询失败则按原流程启动 */ }
        startInspection();
    }

    async function cancelRun() {
        if (currentRunId) {
            try { await fetch(`/api/service-monitor/run/${currentRunId}/cancel`, {method:'POST', credentials:'include'}); } catch(e) {}
        }
        if (evtSource) { evtSource.close(); evtSource = null; }
        finishRun(false, null, null, '巡检已取消');
    }

    window.addEventListener('DOMContentLoaded', checkAndStart);
</script>
{% endblock %}