const API_BASE = "/api";

let allSchemaData = [];
let allImageData  = [];
let isImgScanning = false;

const KNOWN_TABLES = [
    'tbl_site_anomaly',
    'tbl_site_anomaly_history',
    'tbl_site_anomaly_history_bkp'
];

const ALL_DBS = [
    'roadis_nh08','nursultancity','nursultanbypass','nh08_roadis','sh69_poc',
    'sharjahrta','fedrta_poc','athens_poc','johannesburg_poc','uk_poc',
    'rsrdc','ksaaramco_poc','rcyanbu_poc','sr_lnt','Wollondillyshire_poc',
    'SouthAfrica_poc','rcjubail_poc','Wollondillyshire_poc2','Milestone_Infra',
    'Dubai_Metro_POC','a1highwaypoc','Greece_Poc','gekterna_poc','alhayar_poc',
    'parsons_poc','seekright_demo','croatiahighway_poc','seattlecity_poc',
    'JHSW_POC','FMConway_Westminster_POC','airportroad_poc','Brisa_poc',
    'Maple_Highways','cardifftrial_poc','JHSW','hktrpl_poc','qatar_poc',
    'spain_poc','Tahakom_KSA','prs_tollways','JHNSW','E65','baysidecouncil_poc',
    'seattle_poc','phoenix_poc','Peterborough','attiki_poc','atiki_poc',
    'italy_poc','rga_ksahighways','Croatia_demo','croatiastateroad',
    'Maple_ncrepe','pstrpl','DTI','Elevated_Road_Project','Australia_Poc',
    'Toronto_poc','Kazhakhstan_POC','Highway_407_Poc','Aktau_City_Poc',
    'Northern_Coastal_road','Sekura','Australia_FP','Applus_Australia',
    'Japan','Australia_Demo','Irb','Panama','Florida','I595','Almaty_City',
    'MTO','Presight_Abudhabi','Nel','MnDOT','Mexico'
];

// ── Navigation ──
document.querySelectorAll('.nav-item').forEach(btn => {
    btn.addEventListener('click', () => {
        document.querySelectorAll('.nav-item').forEach(b => b.classList.remove('active'));
        document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
        btn.classList.add('active');
        document.getElementById(btn.dataset.target).classList.add('active');
    });
});

// ── Filters ──
function filterSchema() {
    const q = (document.getElementById('schema-search').value || '').toLowerCase();
    const s = document.getElementById('schema-filter').value;
    const t = document.getElementById('schema-table-filter').value;
    renderSchema(allSchemaData, q, s, t);
}
function filterImages() {
    const q = (document.getElementById('image-search').value || '').toLowerCase();
    renderImages(allImageData.filter(d => d.db_name.toLowerCase().includes(q)));
}

// ── Main fetch ──
async function refreshData() {
    try {
        const opts = { credentials: 'include' };
        const [sr, sr2, sr3] = await Promise.all([
            fetch(`${API_BASE}/status`, opts),
            fetch(`${API_BASE}/schema/latest`, opts),
            fetch(`${API_BASE}/image/latest`, opts)
        ]);
        const st = await sr.json();
        const sc = await sr2.json();
        const im = await sr3.json();

        // Scan state UI
        const msgs = [];
        const scanBar    = document.getElementById('scan-bar');
        const scanNotice = document.getElementById('scan-notice');
        const scanFill   = document.getElementById('scan-bar-fill');
        const statusDot  = document.getElementById('status-dot');

        if (st.schema_scanning) {
            msgs.push(`Schema → ${st.schema_current_db || '…'}`);
            document.getElementById('schema-live-dot').classList.add('active');
        } else {
            document.getElementById('schema-live-dot').classList.remove('active');
        }
        if (st.image_scanning) {
            msgs.push(`Images → ${st.image_current_db || '…'}`);
            document.getElementById('image-live-dot').classList.add('active');
        } else {
            document.getElementById('image-live-dot').classList.remove('active');
        }

        if (msgs.length) {
            scanBar.classList.add('visible');
            scanNotice.classList.add('visible');
            document.getElementById('scan-notice-text').textContent = 'Scanning: ' + msgs.join('   ·   ');
            const done = Object.keys(sc).length;
            scanFill.style.width = Math.min((done / ALL_DBS.length) * 100, 99) + '%';
            statusDot.classList.add('scanning');
            document.getElementById('header-status').textContent = 'Scanning…';
        } else {
            scanBar.classList.remove('visible');
            scanNotice.classList.remove('visible');
            statusDot.classList.remove('scanning');
            document.getElementById('header-status').textContent = 'Up to date';
        }

        // Build data
        allSchemaData = ALL_DBS.map(db => {
            const r = sc[db];
            if (r) return { db_name: db, status: r.schema_status, tables: r.schema_tables || [], updated: r.last_updated, pending: false };
            return { db_name: db, status: null, tables: [], updated: null, pending: true };
        });

        isImgScanning = st.image_scanning;
        allImageData = ALL_DBS.map(db => {
            const r = im[db];
            if (r) return { db_name: db, stats: r.image_stats || [], updated: r.last_updated, pending: false };
            return { db_name: db, stats: [], updated: null, pending: true };
        });

        // Chips
        const ok   = allSchemaData.filter(d => !d.pending && d.status === 'Success').length;
        const err  = allSchemaData.filter(d => !d.pending && d.status !== 'Success').length;
        const pend = allSchemaData.filter(d => d.pending).length;
        document.getElementById('chip-total').textContent   = ALL_DBS.length;
        document.getElementById('chip-healthy').textContent = ok;
        document.getElementById('chip-errors').textContent  = err;
        document.getElementById('chip-pending').textContent = pend;

        document.getElementById('nav-schema-status').textContent =
            `${ok} ok · ${err} err · ${pend} pending`;
        document.getElementById('nav-image-status').textContent =
            `${allImageData.filter(d => !d.pending).length} scanned`;

        populateTableDropdown();
        filterSchema();
        filterImages();

    } catch(e) {
        console.error(e);
        document.getElementById('header-status').textContent = 'Offline';
        document.getElementById('status-dot').classList.add('scanning');
    }
}

function populateTableDropdown() {
    const filter = document.getElementById('schema-table-filter');
    const currentVal = filter.value;
    const tables = new Set();
    
    allSchemaData.forEach(db => {
        if (db.tables) db.tables.forEach(t => tables.add(t.table_name));
    });
    
    // Add known tables just in case we are in pending state and they aren't fully populated yet
    KNOWN_TABLES.forEach(t => tables.add(t));
    
    const sorted = Array.from(tables).sort();
    
    filter.innerHTML = '<option value="all">All Tables</option>';
    sorted.forEach(t => {
        const opt = document.createElement('option');
        opt.value = t;
        opt.textContent = t;
        filter.appendChild(opt);
    });
    
    if (sorted.includes(currentVal) || currentVal === 'all') {
        filter.value = currentVal;
    } else {
        filter.value = 'all';
    }
}

// ══════════════════════════════════════
// SCHEMA RENDER
// ══════════════════════════════════════
function renderSchema(data, q = '', statusF = 'all', tableF = 'all') {
    const container = document.getElementById('schema-table-container');

    // Flatten to per-table rows
    let rows = [];
    data.forEach(db => {
        if (db.pending) {
            KNOWN_TABLES.forEach(tn => {
                rows.push({ db_name: db.db_name, table_name: tn, rows: null, cols: null, type: 'pending', updated: null });
            });
            return;
        }
        if (!db.tables || db.tables.length === 0) {
            rows.push({ db_name: db.db_name, table_name: '—', rows: null, cols: null, type: 'error', err_msg: db.status, updated: db.updated });
            return;
        }
        db.tables.forEach(t => {
            rows.push({ db_name: db.db_name, table_name: t.table_name, rows: t.row_count, cols: t.column_count, type: t.status === 'Success' ? 'ok' : 'error', updated: db.updated });
        });
    });

    // Filter
    if (q) rows = rows.filter(r => r.db_name.toLowerCase().includes(q));
    if (statusF === 'success') rows = rows.filter(r => r.type === 'ok');
    if (statusF === 'error')   rows = rows.filter(r => r.type === 'error');
    if (tableF !== 'all')      rows = rows.filter(r => r.table_name === tableF);

    // Compute column mode per table for anomaly detection
    const colMode = {};
    const allTableNames = [...new Set(rows.map(r => r.table_name).filter(t => t !== '—'))];
    allTableNames.forEach(tn => {
        const vals = rows.filter(r => r.table_name === tn && r.cols !== null).map(r => r.cols);
        if (!vals.length) return;
        const freq = {};
        vals.forEach(v => { freq[v] = (freq[v] || 0) + 1; });
        colMode[tn] = parseInt(Object.entries(freq).sort((a,b) => b[1]-a[1])[0][0]);
    });

    if (!rows.length) {
        container.innerHTML = '<div class="empty-state"><span>No results match your filters.</span></div>';
        return;
    }

    // Sort: errors first, pending last, then alpha
    rows.sort((a, b) => {
        if (a.type === 'error' && b.type !== 'error') return -1;
        if (a.type !== 'error' && b.type === 'error') return 1;
        if (a.type === 'pending' && b.type !== 'pending') return 1;
        if (a.type !== 'pending' && b.type === 'pending') return -1;
        return a.db_name.localeCompare(b.db_name);
    });

    let html = `<table class="data-tbl">
        <thead><tr>
            <th style="width:22%">Database</th>
            <th>Table</th>
            <th class="r">Rows</th>
            <th class="r">Columns</th>
            <th>Status</th>
            <th>Last Scan</th>
        </tr></thead>
        <tbody>`;

    rows.forEach(r => {
        const t = r.updated ? new Date(r.updated).toLocaleTimeString([], {hour:'2-digit',minute:'2-digit'}) : '—';

        if (r.type === 'pending') {
            html += `<tr class="row-pending">
                <td class="c-db">${r.db_name}</td>
                <td class="c-tbl">${r.table_name}</td>
                <td class="r c-rows">—</td><td class="r c-cols">—</td>
                <td><span class="badge b-pending">Pending</span></td>
                <td class="c-time">—</td>
            </tr>`;
            return;
        }

        if (r.type === 'error' && r.table_name === '—') {
            html += `<tr class="row-err">
                <td class="c-db">${r.db_name}</td>
                <td class="c-err-msg" colspan="2">${r.err_msg || 'Connection failed'}</td>
                <td></td>
                <td><span class="badge b-err">Error</span></td>
                <td class="c-time">${t}</td>
            </tr>`;
            return;
        }

        const expected = colMode[r.table_name];
        const anomaly  = expected !== undefined && r.cols !== null && r.cols !== expected;
        const colTip   = anomaly ? `title="Expected ${expected} columns (most common)"` : '';

        html += `<tr class="${r.type === 'error' ? 'row-err' : ''}">
            <td class="c-db">${r.db_name}</td>
            <td class="c-tbl">${r.table_name}</td>
            <td class="r c-rows">${r.rows !== null ? Number(r.rows).toLocaleString() : '—'}</td>
            <td class="r c-cols ${anomaly ? 'warn' : ''}" ${colTip}>${r.cols !== null ? r.cols : '—'}${anomaly ? ' ⚠' : ''}</td>
            <td><span class="badge ${r.type === 'ok' ? 'b-ok' : 'b-err'}">${r.type === 'ok' ? '✓ OK' : '✗ Error'}</span></td>
            <td class="c-time">${t}</td>
        </tr>`;
    });

    html += '</tbody></table>';
    container.innerHTML = html;
}

// ══════════════════════════════════════
// IMAGE RENDER
// ══════════════════════════════════════
function renderImages(data) {
    const container = document.getElementById('image-grid-container');
    if (!data || !data.length) {
        container.innerHTML = '<div class="empty-state"><span>No databases match.</span></div>';
        return;
    }

    const sorted = [...data].sort((a, b) => {
        if (!a.pending && b.pending) return -1;
        if (a.pending && !b.pending) return 1;
        return a.db_name.localeCompare(b.db_name);
    });

    let html = '';
    sorted.forEach(db => {
        const map = {};
        (db.stats || []).forEach(s => { map[s.table] = s; });
        const scanned = Object.values(map);

        const agg = scanned.reduce((a, s) => {
            a.tot  += s.total_rows_with_image || 0;
            a.ok   += s.available  || 0;
            a.miss += s.not_found  || 0;
            a.err  += s.error      || 0;
            return a;
        }, {tot:0,ok:0,miss:0,err:0});

        const pOk   = agg.tot > 0 ? (agg.ok   / agg.tot) * 100 : 0;
        const pMiss = agg.tot > 0 ? (agg.miss  / agg.tot) * 100 : 0;
        const pErr  = agg.tot > 0 ? (agg.err   / agg.tot) * 100 : 0;

        const time = db.updated ? new Date(db.updated).toLocaleTimeString([], {hour:'2-digit',minute:'2-digit'}) : '—';

        let badge, badgeClass;
        if (db.pending) {
            badge = isImgScanning ? 'Scanning…' : 'Pending';
            badgeClass = 'b-pending';
        } else {
            badge = pOk >= 95 ? 'Healthy' : pOk >= 70 ? 'Partial' : 'Poor';
            badgeClass = pOk >= 95 ? 'b-ok' : pOk >= 70 ? 'b-warn' : 'b-err';
        }

        let rows = '';
        KNOWN_TABLES.forEach(tn => {
            const s = map[tn];
            if (!s && db.pending) {
                rows += `<tr><td><span class="td-name">${tn}</span></td><td colspan="5" class="td-nil">${isImgScanning ? '⟳ scanning' : '· pending'}</td></tr>`;
            } else if (!s) {
                rows += `<tr><td><span class="td-name absent">${tn}</span></td><td colspan="5" class="td-nil">not in db</td></tr>`;
            } else {
                const tot  = s.total_rows_with_image || 0;
                const ok   = s.available  || 0;
                const miss = s.not_found  || 0;
                const err  = s.error      || 0;
                const pct  = tot > 0 ? ((ok/tot)*100).toFixed(1) : '—';
                const pc   = tot === 0 ? '' : parseFloat(pct) >= 95 ? 'td-ok' : parseFloat(pct) >= 70 ? 'td-warn' : 'td-err';
                rows += `<tr>
                    <td><span class="td-name">${tn}</span></td>
                    <td class="td-num">${tot.toLocaleString()}</td>
                    <td class="td-ok">${ok.toLocaleString()}</td>
                    <td class="td-warn">${miss.toLocaleString()}</td>
                    <td class="td-err">${err.toLocaleString()}</td>
                    <td class="td-pct ${pc}">${pct}${tot>0?'%':''}</td>
                </tr>`;
            }
        });

        html += `<div class="img-card${db.pending ? ' pending' : ''}">
            <div class="card-top">
                <div>
                    <div class="card-db">${db.db_name}</div>
                    <div class="card-meta">${db.pending ? 'Awaiting scan' : `${scanned.length}/3 tables · ${time}`}</div>
                </div>
                <span class="badge ${badgeClass}">${badge}</span>
            </div>

            ${!db.pending ? `
            <div class="card-totals">
                <div class="tot-cell"><div class="tot-v blue">${agg.tot.toLocaleString()}</div><div class="tot-k">Total</div></div>
                <div class="tot-cell"><div class="tot-v green">${agg.ok.toLocaleString()}</div><div class="tot-k">Found</div></div>
                <div class="tot-cell"><div class="tot-v amber">${agg.miss.toLocaleString()}</div><div class="tot-k">Missing</div></div>
                <div class="tot-cell"><div class="tot-v red">${agg.err.toLocaleString()}</div><div class="tot-k">Errors</div></div>
            </div>
            <div class="card-bar">
                <div class="bar-seg green" style="width:${pOk}%"></div>
                <div class="bar-seg amber" style="width:${pMiss}%"></div>
                <div class="bar-seg red" style="width:${pErr}%"></div>
            </div>` : `<div class="card-bar"><div class="bar-shimmer"></div></div>`}

            <table class="bk-table">
                <colgroup>
                    <col style="width: 38%">
                    <col style="width: 15%">
                    <col style="width: 15%">
                    <col style="width: 12%">
                    <col style="width: 10%">
                    <col style="width: 10%">
                </colgroup>
                <thead><tr><th>Table</th><th>Total</th><th>Found</th><th>Miss</th><th>Err</th><th>%</th></tr></thead>
                <tbody>${rows}</tbody>
            </table>
        </div>`;
    });

    container.innerHTML = html || '<div class="empty-state"><span>No data yet.</span></div>';
}

// ── Init ──
refreshData();
setInterval(refreshData, 5000);
