<%#
 Storage Health v3 - Full Dashboard
 eMMC + SoC + Speed + Memory + NAND + Network
-%>

<%
    local uci = require("luci.model.uci").cursor()
    local sys = require("luci.sys")
%>

<%+header%>

<style>
.sh-cards{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:10px;margin:0 0 12px}
.sh-card{background:var(--cbi-background,#fff);border-radius:8px;padding:14px;border:1px solid var(--cbi-border,#e0e0e0)}
.sh-card h2{font-size:12px;color:var(--cbi-muted,#888);font-weight:600;margin:0 0 8px;text-transform:uppercase;letter-spacing:.3px}
.sh-val{font-size:26px;font-weight:700;margin:4px 0;line-height:1.2}
.sh-val.good{color:#27ae60}.sh-val.warn{color:#f39c12}.sh-val.bad{color:#e74c3c}.sh-val.info{color:#3498db}
.sh-sub{font-size:11px;color:var(--cbi-muted,#999);line-height:1.5}
.sh-speed-line{font-size:13px;font-weight:600;color:var(--cbi-text,#333);line-height:1.6}
.sh-speed-line.info{color:#3498db}
.sh-speed-4k{font-size:11px;color:var(--cbi-muted,#999);line-height:1.4}
.sh-net-port{display:flex;align-items:center;gap:6px;margin:3px 0;font-size:12px;font-weight:600}
.sh-net-dot{width:8px;height:8px;border-radius:50%;flex-shrink:0}
.sh-net-dot.up{background:#27ae60;box-shadow:0 0 6px #27ae60}
.sh-net-dot.down{background:#e74c3c}
.sh-bar{height:5px;background:#e0e0e0;border-radius:2px;margin:6px 0;overflow:hidden}
.sh-bar-fill{height:100%;border-radius:2px;transition:width .5s}
.sh-btns{display:flex;flex-wrap:wrap;gap:6px;margin:0 0 12px}
.sh-btn{border:none;padding:6px 14px;border-radius:6px;font-size:12px;font-weight:600;cursor:pointer;transition:all .2s}
.sh-btn:hover{opacity:.85;transform:translateY(-1px)}
.sh-btn:disabled{opacity:.4;cursor:not-allowed}
.sh-btn-run{background:linear-gradient(135deg,#667eea,#764ba2);color:#fff}
.sh-btn-test{background:#3498db;color:#fff}
.sh-btn-warn{background:#e67e22;color:#fff}
.sh-btn-full{background:#27ae60;color:#fff}
.sh-btn-nand{background:#8e44ad;color:#fff}
.sh-btn-soc{background:#e84393;color:#fff}
.sh-out{background:#1a1a2e;color:#00e676;font-family:monospace;font-size:11px;padding:10px;border-radius:6px;max-height:350px;overflow-y:auto;white-space:pre-wrap;line-height:1.4;margin-top:10px}
.sh-credit{text-align:right;margin-top:3px;font-size:10px;color:var(--cbi-muted,#666)}
.sh-credit a{color:var(--cbi-muted,#666);text-decoration:none}
.sh-empty{text-align:center;color:var(--cbi-muted,#bbb);font-size:12px;padding:8px 0}
</style>

<div class="cbi-map">
<h2 name="content"><%:Storage Health%> - 存储健康诊断</h2>

<div class="sh-btns" style="margin-top:8px">
    <button class="sh-btn sh-btn-run cbi-button" onclick="shTest('overview')">快速概览</button>
    <button class="sh-btn sh-btn-test cbi-button" onclick="shMemory('quick')">内存快检</button>
    <button class="sh-btn sh-btn-warn cbi-button" onclick="shMemory('stress')">内存压力</button>
    <button class="sh-btn cbi-button" onclick="shTest('speed')">速度测试</button>
    <button class="sh-btn sh-btn-nand cbi-button" onclick="shNandBadblocks()">NAND坏块</button>
    <button class="sh-btn cbi-button" onclick="shPartition()">查看分区</button>
    <button class="sh-btn sh-btn-soc cbi-button" onclick="shCoremark('run')">跑分</button>
    <button class="sh-btn sh-btn-full cbi-button" onclick="shFull()">完整诊断</button>
</div>

<div class="sh-cards">
    <!-- eMMC -->
    <div class="sh-card">
        <h2>💾 eMMC <span style="font-weight:400;font-size:11px" id="sh-cap">--</span></h2>
        <div id="sh-emmc-body">
            <div class="sh-val info" id="sh-eol">--</div>
            <div class="sh-sub" id="sh-eol-label">点击检测</div>
            <div class="sh-sub" id="sh-bus" style="margin-top:2px">--</div>
            <div class="sh-bar"><div class="sh-bar-fill" id="sh-eolbar" style="width:0;background:#27ae60"></div></div>
        </div>
        <div id="sh-emmc-empty" class="sh-empty" style="display:none">此机无eMMC</div>
    </div>
    <!-- SoC -->
    <div class="sh-card">
        <h2>🖥 系统</h2>
        <div class="sh-sub" style="font-size:13px;font-weight:600;color:var(--cbi-text)" id="sh-soc-name">--</div>
        <div class="sh-sub" id="sh-soc-cpu">--</div>
        <div class="sh-speed-line" style="margin-top:4px" id="sh-coremark">--</div>
        <div class="sh-sub" id="sh-coremark-sub">--</div>
    </div>
    <!-- Manufacturer -->
    <div class="sh-card">
        <h2>🏭 制造商</h2>
        <div class="sh-val" style="font-size:18px" id="sh-mfr">--</div>
        <div class="sh-sub" id="sh-prod">--</div>
    </div>
    <!-- Speed -->
    <div class="sh-card">
        <h2>⚡ 速度</h2>
        <div class="sh-speed-line" id="sh-speed-seq">--</div>
        <div class="sh-speed-4k" id="sh-speed-4k">--</div>
    </div>
    <!-- Memory -->
    <div class="sh-card">
        <h2>🧠 内存</h2>
        <div class="sh-val" id="sh-mem-val">--</div>
        <div class="sh-sub" id="sh-mem-info">--</div>
        <div class="sh-sub" id="sh-mem-speed" style="line-height:1.5">--</div>
        <div class="sh-sub" id="sh-mem-ddr" style="font-size:10px;margin-top:2px">--</div>
    </div>
    <!-- NAND -->
    <div class="sh-card">
        <h2>💿 NAND</h2>
        <div id="sh-nand-body">
            <div class="sh-val" id="sh-nand">--</div>
            <div class="sh-sub" id="sh-nand-info">--</div>
            <div class="sh-sub" id="sh-nand-mfr" style="font-size:10px">--</div>
        </div>
        <div id="sh-nand-empty" class="sh-empty" style="display:none">此机无NAND</div>
    </div>
    <!-- Network -->
    <div class="sh-card">
        <h2>🔌 网络</h2>
        <div id="sh-net-ports">--</div>
        <div class="sh-sub" id="sh-net-wifi" style="margin-top:4px">--</div>
    </div>
</div>

<h3>诊断输出</h3>
<div class="sh-out" id="sh-output">点击上方按钮开始...</div>
<div class="sh-credit">by <strong>数码罗记</strong> · <a href="https://godsun.pro" target="_blank">godsun.pro</a></div>
</div>

<script>
var SH_PREFIX = '<%=luci.dispatcher.build_url("admin", "storage_health")%>';

function shFetch(endpoint, params) {
    var el = document.getElementById('sh-output');
    el.textContent = '⏳ 执行中...';
    var url = SH_PREFIX + '/' + endpoint;
    if (params) {
        var qs = Object.keys(params).map(function(k){return k+'='+encodeURIComponent(params[k])}).join('&');
        url += '?' + qs;
    }
    return fetch(url)
        .then(function(r){return r.json()})
        .then(function(d){
            el.textContent = d._raw || JSON.stringify(d, null, 2);
            return d;
        })
        .catch(function(e){
            el.textContent = '❌ ' + e.message;
            return {};
        });
}

function shUpdateDashboard(d) {
    // eMMC
    if (d.eMMC_STATUS && d.eMMC_STATUS.indexOf('未检测到')<0) {
        document.getElementById('sh-emmc-body').style.display='';
        document.getElementById('sh-emmc-empty').style.display='none';
        var eol = d.eMMC_EOL_PCT ? parseInt(d.eMMC_EOL_PCT) : 0;
        var el = document.getElementById('sh-eol'), bar = document.getElementById('sh-eolbar');
        el.textContent = eol + '%';
        bar.style.width = eol + '%';
        el.className = 'sh-val ' + (eol>70?'good':eol>30?'warn':'bad');
        bar.style.background = eol>70?'#27ae60':eol>30?'#f39c12':'#e74c3c';
        if (d.eMMC_STATUS) document.getElementById('sh-eol-label').textContent = d.eMMC_STATUS;
        if (d.eMMC_BUS_MODE) document.getElementById('sh-bus').textContent = '总线: ' + d.eMMC_BUS_MODE;
        if (d.CAPACITY_GB || d.eMMC_CAPACITY) document.getElementById('sh-cap').textContent = d.CAPACITY_GB || d.eMMC_CAPACITY;
    } else if (d.eMMC_STATUS && d.eMMC_STATUS.indexOf('未检测到')>=0) {
        document.getElementById('sh-emmc-body').style.display='none';
        document.getElementById('sh-emmc-empty').style.display='';
    }

    // SoC
    if (d.SOC_NAME) document.getElementById('sh-soc-name').textContent = d.SOC_NAME;
    if (d.SOC_CPU) document.getElementById('sh-soc-cpu').textContent = d.SOC_CPU;
    if (d.SOC_COREMARK && d.SOC_COREMARK!='N/A') {
        document.getElementById('sh-coremark').textContent = d.SOC_COREMARK;
        document.getElementById('sh-coremark').className = 'sh-speed-line info';
        document.getElementById('sh-coremark-sub').textContent = 'CoreMark分数';
        if (d.SOC_COREMARK_PER_CORE) document.getElementById('sh-coremark-sub').textContent += ' | 单核≈'+d.SOC_COREMARK_PER_CORE;
    }
    if (d.COREMARK_SCORE && d.COREMARK_SCORE!='N/A') {
        document.getElementById('sh-coremark').textContent = d.COREMARK_SCORE;
        document.getElementById('sh-coremark-sub').textContent = 'CoreMark分数';
    }

    // Manufacturer
    if (d.MANUFACTURER) document.getElementById('sh-mfr').textContent = d.MANUFACTURER;
    if (d.PRODUCT) {
        var pt = '产品: ' + d.PRODUCT;
        if (d.EMMC_VERSION) pt += ' | eMMC ' + d.EMMC_VERSION;
        document.getElementById('sh-prod').textContent = pt;
    }

    // Speed
    if (d.SEQ_WRITE_SPEED || d.SEQ_READ_SPEED) {
        document.getElementById('sh-speed-seq').innerHTML =
            '<div>写: ' + (d.SEQ_WRITE_SPEED||'?') + '</div>' +
            '<div>读: ' + (d.SEQ_READ_SPEED||'?') + '</div>';
        document.getElementById('sh-speed-4k').innerHTML =
            '<div>4K写: ' + (d['4K_WRITE_IOPS']||0) + ' IOPS</div>' +
            '<div>4K读: ' + (d['4K_READ_IOPS']||0) + ' IOPS</div>';
    }

    // Memory
    if (d.MEM_TOTAL_MB) {
        document.getElementById('sh-mem-info').textContent = '总: ' + d.MEM_TOTAL_MB;
        if (d.MEM_WRITE_SPEED || d.MEM_READ_SPEED) {
            document.getElementById('sh-mem-speed').innerHTML =
                '<div>写: ' + (d.MEM_WRITE_SPEED||'?') + ' MB/s</div>' +
                '<div>读: ' + (d.MEM_READ_SPEED||'?') + ' MB/s</div>';
        }
        if (d.MEM_DDR_TYPE && d.MEM_DDR_TYPE!='未知') {
            document.getElementById('sh-mem-ddr').textContent = d.MEM_DDR_TYPE;
            if (d.MEM_DDR_FREQ && d.MEM_DDR_FREQ!='未知') document.getElementById('sh-mem-ddr').textContent += ' @ ' + d.MEM_DDR_FREQ;
        }
        if (d.MEM_VERDICT) {
            document.getElementById('sh-mem-val').textContent = d.MEM_VERDICT;
            document.getElementById('sh-mem-val').className = 'sh-val ' + (d.MEM_VERDICT.indexOf('PASS')>=0?'good':'warn');
        }
    }

    // NAND
    if (d.NAND_HEALTH) {
        if (d.NAND_HEALTH.indexOf('N/A')>=0 || d.NAND_HEALTH.indexOf('未检测到')>=0) {
            document.getElementById('sh-nand-body').style.display='none';
            document.getElementById('sh-nand-empty').style.display='';
        } else {
            document.getElementById('sh-nand-body').style.display='';
            document.getElementById('sh-nand-empty').style.display='none';
            document.getElementById('sh-nand').textContent = d.NAND_HEALTH;
            var ni = (d.NAND_MTD_COUNT||'?') + ' 分区';
            if (d.NAND_TOTAL_CAPACITY) ni += ' | ' + d.NAND_TOTAL_CAPACITY;
            document.getElementById('sh-nand-info').textContent = ni;
            if (d.NAND_MANUFACTURER) document.getElementById('sh-nand-mfr').textContent = '厂商: ' + d.NAND_MANUFACTURER;
        }
    } else if (d.NAND_BADBLOCK_VERDICT) {
        document.getElementById('sh-nand-body').style.display='';
        document.getElementById('sh-nand-empty').style.display='none';
        document.getElementById('sh-nand').textContent = d.NAND_BADBLOCK_VERDICT;
        document.getElementById('sh-nand-info').textContent = '坏块: ' + (d.NAND_BADBLOCK_TOTAL||'?');
    }

    // Network
    if (d.NET_PORT_COUNT || d.NET_WIFI_COUNT) {
        var nh = '';
        for (var i=0; i<20; i++) {
            var p = d['NET_P'+i];
            if (!p) break;
            var parts = p.split(':');
            var name=parts[0], speed=parts[1], link=parts[2];
            var cls = (link=='up') ? 'up' : 'down';
            nh += '<div class="sh-net-port"><span class="sh-net-dot '+cls+'"></span>'+name+' ';
            if (link=='up') nh += speed; else nh += '未连接';
            nh += '</div>';
        }
        if (nh) document.getElementById('sh-net-ports').innerHTML = nh;
        var wf = '';
        if (d.NET_WIFI_COUNT && parseInt(d.NET_WIFI_COUNT)>0) {
            wf = '📶 WiFi: ';
            for (var j=0; j<10; j++) {
                var w = d['NET_WIFI'+j];
                if (!w) break;
                var wp = w.split(':');
                var nb = wp[0].split('@');  // name@band
                var name = nb[0], band = nb[1]||'';
                var link = wp[1];
                var mode = wp[2]||'';
                var maxRate = wp[3]||'';
                wf += name + (link=='up'?' ✅':' ❌');
                if (band) wf += ' ' + band;
                if (maxRate && maxRate!='?') wf += ' 最大' + maxRate;
                wf += ' ';
            }
        }
        document.getElementById('sh-net-wifi').innerHTML = wf;
    } else if (d.PART_VERDICT) {
        // Don't overwrite network from partition view
    }
}

function shTest(ep) {
    var map = {overview:'api_detail',emmc:'api_health',speed:'api_speed',nand:'api_nand'};
    var e = map[ep]||('api_'+ep);
    return shFetch(e).then(shUpdateDashboard);
}

function shMemory(mode) {
    var p = {mode: mode};
    if (mode==='stress') { p.size=64; p.duration=30; }
    else p.size = 128;
    return shFetch('api_memory', p).then(shUpdateDashboard);
}

function shNandBadblocks() {
    return shFetch('api_nand_badblocks', {mode:'quick'}).then(shUpdateDashboard);
}

function shPartition() {
    return shFetch('api_partition').then(shUpdateDashboard);
}

function shCoremark(mode) {
    return shFetch('api_coremark', {mode:mode||'read'}).then(shUpdateDashboard);
}

function shFull() {
    return shFetch('api_smart', {mode:'quick'}).then(shUpdateDashboard);
}

// Auto-load: overview + soc + network on page open
document.addEventListener('DOMContentLoaded', function(){
    shTest('overview');
    shFetch('api_soc').then(shUpdateDashboard);
    shFetch('api_network').then(shUpdateDashboard);
});
</script>

<%+footer%>
