/**
 * commerce blueprint · wiring seam for `@platform-modules/ledger`.
 *
 * Adapter-minimalism (CLAUDE.md §4): stand up the append-only ledger_entries journal on an in-memory
 * pglite and expose the module's real `appendEntry` as the `LedgerSeam` billing injects (PATTERN B:
 * ledger sits ABOVE billing — billing receives a `{ appendEntry }` bag, it does not import ledger
 * internals). A real host registers ledger's schema into its own Drizzle migration set.
 *
 * SOURCE-OF-TRUTH NOTE (a real contract detail this hand-build surfaced): `appendEntry` writes ONLY to
 * the append-only `ledger_entries` journal — it does NOT maintain the optional `wallet_balances`
 * projection (`getBalance({kind:'wallet'})` stays 0 unless the host maintains that column itself). So
 * the blueprint proves settlement by SUMMING the journal, never by reading the wallet projection.
 */
import { PGlite } from '@electric-sql/pglite'
import { drizzle } from 'drizzle-orm/pglite'
import {
  appendEntry,
  ledgerEntries,
  ledgerSchema,
  type LedgerSchema,
} from '@platform-modules/ledger'
import type { Querier } from '@platform-modules/db'
import type { LedgerSeam } from '@platform-modules/billing'

export type LedgerDb = Querier<LedgerSchema>

export type CommerceLedger = {
  db: LedgerDb
  /** The bag billing injects (Pattern B). `appendEntry` is the module's real export, unchanged. */
  seam: LedgerSeam
  /** Inspect the append-only journal: how many entries, and their signed-delta sum (agorot). */
  journal(): Promise<{ count: number; sum: bigint }>
}

export async function createCommerceLedger(): Promise<CommerceLedger> {
  const client = new PGlite()
  const db = drizzle(client, { schema: ledgerSchema }) as unknown as LedgerDb

  await client.exec(`
    CREATE TABLE ledger_entries (
      id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
      delta bigint NOT NULL,
      currency text,
      reason text NOT NULL,
      ref jsonb,
      idempotency_key text NOT NULL,
      created_at timestamptz NOT NULL DEFAULT NOW()
    );
    CREATE UNIQUE INDEX ledger_entries_idempotency_key_uq ON ledger_entries (idempotency_key);
    CREATE TABLE wallet_balances (
      owner_id text PRIMARY KEY,
      balance bigint NOT NULL DEFAULT 0,
      updated_at timestamptz NOT NULL DEFAULT NOW()
    );
  `)

  return {
    db,
    // The sanctioned bridge: billing's LedgerSeam is generic (`S extends Schema`) while ledger's
    // appendEntry is narrowed (`S extends LedgerSchema`), so they do not unify directly. The cast is
    // the module author's OWN pattern — see `asLedgerSeam()` in packages/billing/src/index.test.ts —
    // and is sound because appendEntry only inserts into `ledger_entries`, which the host's combined
    // schema always includes. NOT a swap-survival break; the seam stays `{ appendEntry }`.
    seam: { appendEntry: appendEntry as LedgerSeam['appendEntry'] },
    async journal() {
      const rows = await db.select({ delta: ledgerEntries.delta }).from(ledgerEntries)
      return { count: rows.length, sum: rows.reduce((acc, row) => acc + row.delta, 0n) }
    },
  }
}
