/** TRUE cross-thread two-writer test: a worker thread and the main thread each
 *  hammer UPDATEs on their own write connection to one WAL file for 3s. Counts
 *  SQLITE_BUSY ("database is locked") under each busy-handling mode. This is the
 *  real scenario the sync worker + main thread are in. */
import { DatabaseSync } from "node:sqlite";
import { Worker } from "node:worker_threads";
import fs from "node:fs";
import path from "node:path";
import os from "node:os";
import { fileURLToPath } from "node:url";

const here = path.dirname(fileURLToPath(import.meta.url));
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), "rmf-2wt-"));
const dbPath = path.join(tmp, "t.db");

function fresh() {
    try { for (const s of ["", "-wal", "-shm"]) fs.rmSync(dbPath + s, { force: true }); } catch {}
    const d = new DatabaseSync(dbPath);
    d.exec("PRAGMA journal_mode = WAL");
    d.exec("CREATE TABLE t (id INTEGER PRIMARY KEY, v TEXT)");
    for (let i = 0; i < 200; i++) d.prepare("INSERT INTO t (id,v) VALUES (?,?)").run(i, "x");
    d.close();
}

async function run(mode, ms) {
    fresh();
    const worker = new Worker(path.join(here, "two-writer-worker.mjs"), { workerData: { dbPath, mode, ms, tag: "W" } });
    const workerDone = new Promise(res => worker.once("message", res));
    // Main thread connection.
    const opts = mode === "ctor" ? { timeout: ms } : {};
    const d = new DatabaseSync(dbPath, opts);
    if (mode === "pragma") d.exec(`PRAGMA busy_timeout = ${ms}`);
    let ok = 0, locks = 0;
    const end = Date.now() + 3000;
    while (Date.now() < end) {
        try { d.prepare("UPDATE t SET v=? WHERE id=?").run(`M-${ok}`, ok % 200); ok++; }
        catch (e) { if (/locked|busy/i.test(e.message)) locks++; else throw e; }
    }
    d.close();
    const w = await workerDone;
    await worker.terminate();
    console.log(`  mode=${mode.padEnd(7)} timeout=${ms}ms → main: ${ok} ok/${locks} locked | worker: ${w.ok} ok/${w.locks} locked`);
    return locks + w.locks;
}

console.log(`\ncross-thread two-writer test (node ${process.version})\n`);
await run("none", 0);
await run("pragma", 5000);
await run("ctor", 5000);
try { fs.rmSync(tmp, { recursive: true, force: true }); } catch {}
console.log("");
