import { describe, expect, test } from "bun:test";
import type { Db, Dialect, Driver, ExecResult, Row, TxHandle } from "@wrnexus/db";
import { dbPermissionStore } from "../src/db.ts";

/**
 * A deterministic regression guard for C1/C2 (round-1 review): grant() used to
 * wrap its delete-then-insert in db.tx, and the sqlite driver runs a bare
 * BEGIN on one shared, unserialized connection - so an open transaction there
 * could sweep in and discard a concurrent bare write from another method.
 * Timing-based tests can't reliably prove the absence of that; this can,
 * because it needs no concurrency at all - it just asserts the store never
 * asks the driver to open a transaction in the first place.
 */
function makeFakeDb(): { db: Db; statements: string[]; transactionCalls: number } {
  const statements: string[] = [];
  const stats = { transactionCalls: 0 };

  const driver: Driver = {
    dialect: "sqlite" as Dialect,
    async query(sql: string): Promise<Row[]> {
      statements.push(sql);
      return [];
    },
    async exec(sql: string): Promise<ExecResult> {
      statements.push(sql);
      return { changes: 0 };
    },
    async transaction<T>(fn: (tx: TxHandle) => Promise<T>): Promise<T> {
      // The spy: this must never be called by a transaction-free store.
      stats.transactionCalls++;
      statements.push("BEGIN");
      return fn(driver);
    },
    close() {},
  };

  const db: Db = {
    driver,
    async all<T = Row>(sql: string): Promise<T[]> {
      statements.push(sql);
      return [];
    },
    async one<T = Row>(sql: string): Promise<T | null> {
      statements.push(sql);
      return null;
    },
    async exec(sql: string): Promise<ExecResult> {
      statements.push(sql);
      return { changes: 0 };
    },
    async tx<T>(fn: (tx: Db) => Promise<T>): Promise<T> {
      // Routed through the same driver.transaction spy a real Db would use.
      return driver.transaction(() => fn(db));
    },
    async createTable() {},
    close() {},
  };

  return {
    db,
    statements,
    get transactionCalls() {
      return stats.transactionCalls;
    },
  };
}

describe("dbPermissionStore opens no transaction", () => {
  test("the store opens no transaction: a shared-connection rollback would discard concurrent writes from other methods", async () => {
    const fake = makeFakeDb();
    const store = dbPermissionStore(fake.db);

    await store.assignmentsFor("u1");
    await store.assignRole("u1", "editor");
    await store.revokeRole("u1", "editor");
    await store.grant("u1", "post:write", "allow");
    await store.revokeGrant("u1", "post:write");
    await store.listSubjects();

    expect(fake.transactionCalls).toBe(0);
    for (const sql of fake.statements) {
      expect(sql).not.toContain("BEGIN");
    }
  });
});
