/**
 * One-time back-population of api_uploaded_at from server_inventory.txt.
 *
 * Reads SN list, UPDATEs test_records.api_uploaded_at = NOW() in batches
 * for records whose serial_number appears in the inventory.
 *
 * Usage: node back-populate-api-uploaded.js [--inventory path] [--batch 1000] [--dry-run]
 */
const fs = require('fs');
const db = require('./db');

const args = process.argv.slice(2);
const arg = (n, d) => { const i = args.indexOf(n); return i >= 0 ? args[i+1] : d; };
const flag = n => args.includes(n);

const INVENTORY = arg('--inventory', 'C:\\ProgramData\\dataforth-uploader\\server_inventory.txt');
const BATCH = parseInt(arg('--batch', '1000'), 10);
const DRY = flag('--dry-run');

async function main() {
    if (!fs.existsSync(INVENTORY)) {
        console.error(`[FAIL] inventory not found: ${INVENTORY}`);
        process.exit(1);
    }

    const data = fs.readFileSync(INVENTORY, 'utf8');
    const sns = data.split(/\r?\n/).map(s => s.trim()).filter(Boolean);
    console.log(`[INFO] inventory: ${sns.length} serial numbers`);
    console.log(`[INFO] batch size: ${BATCH}  dry-run: ${DRY}`);

    const t0 = Date.now();
    let totalMatched = 0;

    for (let i = 0; i < sns.length; i += BATCH) {
        const chunk = sns.slice(i, i + BATCH);
        const placeholders = chunk.map((_, j) => `$${j + 1}`).join(',');
        if (DRY) {
            const row = await db.queryOne(
                `SELECT COUNT(*) as c FROM test_records WHERE serial_number IN (${placeholders}) AND api_uploaded_at IS NULL`,
                chunk,
            );
            totalMatched += parseInt(row.c, 10) || 0;
        } else {
            const result = await db.execute(
                `UPDATE test_records SET api_uploaded_at = NOW() WHERE serial_number IN (${placeholders}) AND api_uploaded_at IS NULL`,
                chunk,
            );
            totalMatched += result.rowCount || 0;
        }
        if ((i / BATCH) % 20 === 0) {
            const rate = (i + chunk.length) / Math.max(1, (Date.now() - t0) / 1000);
            const eta = Math.round((sns.length - i - chunk.length) / Math.max(1, rate));
            console.log(`  progress ${i + chunk.length}/${sns.length}  matched-so-far=${totalMatched}  rate=${rate.toFixed(0)}/s  eta=${eta}s`);
        }
    }

    const elapsed = ((Date.now() - t0) / 1000).toFixed(1);
    console.log(`\n[DONE] ${elapsed}s`);
    console.log(`  inventory size: ${sns.length}`);
    console.log(`  ${DRY ? 'would update' : 'updated'}: ${totalMatched}`);

    // Sanity: how many records have api_uploaded_at set vs null?
    const tot = await db.queryOne(`SELECT COUNT(*) as c FROM test_records`);
    const set = await db.queryOne(`SELECT COUNT(*) as c FROM test_records WHERE api_uploaded_at IS NOT NULL`);
    const nul = await db.queryOne(`SELECT COUNT(*) as c FROM test_records WHERE api_uploaded_at IS NULL`);
    console.log(`\n[DB STATE]`);
    console.log(`  total records:         ${tot.c}`);
    console.log(`  api_uploaded_at SET:   ${set.c}`);
    console.log(`  api_uploaded_at NULL:  ${nul.c}`);

    await db.close();
}

main().catch(e => { console.error('[FATAL]', e); process.exit(1); });
