const fmt = n => n == null ? '—' : Number(n).toLocaleString('vi-VN');

function formatTTL(ttl) {
    if (ttl === -1) return '∞ no expiry';
    if (ttl === -2) return '⚠ expired';
    if (ttl > 86400) return Math.floor(ttl/86400) + 'd ' + Math.floor((ttl%86400)/3600) + 'h';
    if (ttl > 3600) return Math.floor(ttl/3600) + 'h ' + Math.floor((ttl%3600)/60) + 'm';
    if (ttl > 60) return Math.floor(ttl/60) + 'm ' + (ttl%60) + 's';
    return ttl + 's';
}

function formatSize(b) {
    if (b < 0) return '—';
    if (b < 1024) return b + ' B';
    if (b < 1048576) return (b/1024).toFixed(1) + ' KB';
    return (b/1048576).toFixed(2) + ' MB';
}

function showToast(msg, type='success') {
    const t = document.getElementById('toast');
    t.textContent = msg;
    t.className = 'toast ' + type + ' show';
    setTimeout(() => t.classList.remove('show'), 3000);
}

// Clock
setInterval(() => {
    const el = document.getElementById('clock');
    if (el) el.textContent = new Date().toLocaleTimeString('vi-VN', {hour:'2-digit',minute:'2-digit',second:'2-digit'});
}, 1000);

// ═══ TABS ═══
function switchTab(name, el) {
    document.querySelectorAll('.cache-tab').forEach(t => t.classList.remove('active'));
    el.classList.add('active');
    document.getElementById('tab-cat').style.display = name === 'cat' ? 'block' : 'none';
    document.getElementById('tab-keys').style.display = name === 'keys' ? 'block' : 'none';
    if (name === 'keys') loadKeys();
}

// ═══ MODAL ═══
async function viewKey(key) {
    document.getElementById('modal').classList.add('show');
    document.getElementById('m-title').textContent = 'Loading...';
    document.getElementById('m-key').textContent = key;
    document.getElementById('m-type').textContent = '...';
    document.getElementById('m-ttl').textContent = '...';
    document.getElementById('m-value').textContent = 'Loading...';

    try {
        const r = await fetch('/api/cache/get?key=' + encodeURIComponent(key));
        const d = await r.json();
        if (d.error) throw new Error(d.error);

        // Shorten title
        const shortKey = key.length > 40 ? key.substring(0, 20) + '...' + key.substring(key.length - 15) : key;
        document.getElementById('m-title').textContent = shortKey;
        document.getElementById('m-type').textContent = d.type;
        document.getElementById('m-ttl').textContent = formatTTL(d.ttl);

        // Pretty print value
        let display;
        if (typeof d.value === 'object') {
            display = JSON.stringify(d.value, null, 2);
        } else {
            display = String(d.value);
        }
        document.getElementById('m-value').textContent = display;
    } catch(e) {
        document.getElementById('m-value').textContent = '❌ Error: ' + e.message;
    }
}

function closeModal() { document.getElementById('modal').classList.remove('show'); }
document.addEventListener('keydown', e => { if (e.key === 'Escape') closeModal(); });

// ═══ LOAD STATS ═══
const CAT_COLORS = ['#6366f1','#10b981','#f59e0b','#ef4444','#8b5cf6','#06b6d4','#ec4899','#84cc16','#f97316','#14b8a6'];

async function loadStats() {
    try {
        const r = await fetch('/api/cache/stats');
        const d = await r.json();
        if (d.error) throw new Error(d.error);

        document.getElementById('s-keys').textContent = fmt(d.total_keys);
        document.getElementById('s-mem').textContent = d.memory_used || '—';
        document.getElementById('s-peak').textContent = d.memory_peak || '—';
        document.getElementById('s-rhit').textContent = fmt(d.in_memory_stats?.resp_hits || 0);
        document.getElementById('s-ehit').textContent = fmt(d.in_memory_stats?.emb_hits || 0);
        document.getElementById('s-miss').textContent = fmt(d.in_memory_stats?.misses || 0);
        document.getElementById('topbar-meta').textContent = fmt(d.total_keys) + ' keys · ' + d.memory_used + ' · Redis ✓';

        // Render categories
        const cats = d.categories || {};
        const sorted = Object.entries(cats).sort((a,b) => b[1].count - a[1].count);

        if (!sorted.length) {
            document.getElementById('cat-container').innerHTML = '<div class="empty">📭 Cache trống — chưa có key nào</div>';
            return;
        }

        document.getElementById('cat-container').innerHTML = '<div class="cat-grid">' + sorted.map(([name, cat], i) => {
            const color = CAT_COLORS[i % CAT_COLORS.length];
            const keys = (cat.keys || []).map(k =>
                `<div class="ck-row" onclick="viewKey('${k.key.replace(/'/g,"\\'")}')">
                    <span class="ck-key" title="${k.key}">${k.key}</span>
                    <span class="ck-ttl ${k.ttl > 0 && k.ttl < 300 ? 'hot' : ''}">${formatTTL(k.ttl)}</span>
                </div>`
            ).join('');
            const remaining = cat.count - (cat.keys || []).length;
            const loadMoreBtn = remaining > 0
                ? `<button class="cat-more" id="more-${i}" onclick="loadMoreKeys('${name}', ${i})">📋 Load ${remaining} keys còn lại</button>`
                : '';
            return `<div class="cat-card">
                <div class="cat-head">
                    <span class="cat-name">${name}</span>
                    <span class="cat-badge" style="background:${color}">${cat.count}</span>
                </div>
                <div class="cat-keys-list" id="keylist-${i}">${keys}</div>
                ${loadMoreBtn}
                <button class="cat-clear" onclick="clearCat('${name}')">🗑️ Clear ${name}:*</button>
            </div>`;
        }).join('') + '</div>';
    } catch(e) {
        document.getElementById('cat-container').innerHTML = '<div class="empty">❌ ' + e.message + '</div>';
        document.getElementById('topbar-meta').textContent = 'Redis unavailable';
    }
}

// ═══ LOAD MORE KEYS IN CATEGORY ═══
async function loadMoreKeys(prefix, idx) {
    const btn = document.getElementById('more-' + idx);
    if (btn) btn.textContent = '⏳ Loading...';

    try {
        const r = await fetch('/api/cache/keys?pattern=' + encodeURIComponent(prefix + ':*') + '&limit=500');
        const d = await r.json();
        if (d.error) throw new Error(d.error);

        const list = document.getElementById('keylist-' + idx);
        list.classList.add('expanded');
        list.innerHTML = (d.keys || []).map(k =>
            `<div class="ck-row" onclick="viewKey('${k.key.replace(/'/g,"\\'")}')">
                <span class="ck-key" title="${k.key}">${k.key}</span>
                <span class="ck-ttl ${k.ttl > 0 && k.ttl < 300 ? 'hot' : ''}">${formatTTL(k.ttl)}</span>
            </div>`
        ).join('');

        if (btn) btn.remove();
    } catch(e) {
        if (btn) btn.textContent = '❌ Error';
        showToast('Error: ' + e.message, 'error');
    }
}

// ═══ LOAD KEYS ═══
async function loadKeys() {
    const pattern = document.getElementById('pat-input').value.trim() || '*';
    const c = document.getElementById('keys-container');
    c.innerHTML = '<div class="loading"><div class="spinner"></div>Scanning keys...</div>';

    try {
        const r = await fetch('/api/cache/keys?pattern=' + encodeURIComponent(pattern) + '&limit=200');
        const d = await r.json();
        if (d.error) throw new Error(d.error);

        if (!d.keys?.length) {
            c.innerHTML = '<div class="empty">📭 No keys matching "' + pattern + '"</div>';
            return;
        }

        c.innerHTML = `<table class="keys-tbl">
            <thead><tr><th>#</th><th>Key</th><th>Type</th><th>Size</th><th>TTL</th></tr></thead>
            <tbody>${d.keys.map((k, i) =>
                `<tr onclick="viewKey('${k.key.replace(/'/g,"\\'")}')">
                    <td style="color:#aaa">${i+1}</td>
                    <td><span class="key-mono" title="${k.key}">${k.key}</span></td>
                    <td><span class="type-pill type-${k.type}">${k.type}</span></td>
                    <td style="font-size:12px;color:#888">${formatSize(k.size)}</td>
                    <td style="font-size:12px;color:#888">${formatTTL(k.ttl)}</td>
                </tr>`
            ).join('')}</tbody>
        </table>
        <div style="font-size:11px;color:#aaa;margin-top:8px;text-align:right">${d.count} keys found</div>`;
    } catch(e) {
        c.innerHTML = '<div class="empty">❌ ' + e.message + '</div>';
    }
}

// ═══ CLEAR ACTIONS ═══
async function clearCat(prefix) {
    if (!confirm('🗑️ Clear all "' + prefix + ':*" keys?')) return;
    try {
        const r = await fetch('/api/cache/clear?pattern=' + encodeURIComponent(prefix + ':*'), {method:'POST'});
        const d = await r.json();
        showToast('🗑️ Deleted ' + d.deleted + ' keys');
        loadAll();
    } catch(e) { showToast('Error: ' + e.message, 'error'); }
}

async function clearByPattern() {
    const p = document.getElementById('pat-input').value.trim() || 'resp_cache:*';
    if (!confirm('🗑️ Clear all keys matching "' + p + '"?')) return;
    try {
        const r = await fetch('/api/cache/clear?pattern=' + encodeURIComponent(p), {method:'POST'});
        const d = await r.json();
        showToast('🗑️ Deleted ' + d.deleted + ' keys');
        loadAll();
    } catch(e) { showToast('Error: ' + e.message, 'error'); }
}

async function clearAll() {
    if (!confirm('💥 FLUSH ALL CACHE?\nThis will delete ALL cached data!')) return;
    if (!confirm('⚠️ Are you really sure? This cannot be undone.')) return;
    try {
        const r = await fetch('/api/cache/clear-all', {method:'POST'});
        showToast('💥 All cache flushed!');
        loadAll();
    } catch(e) { showToast('Error: ' + e.message, 'error'); }
}

// ═══ INIT ═══
async function loadAll() { await loadStats(); }
loadAll();