function generatePgClient(_context) {
  return `/**
 * Postgres native (pg) \u2014 singleton pool + helpers.
 *
 * Picks up POSTGRES_URL or DATABASE_URL from the environment. The pool is
 * lazily initialised on first use and reused across requests; \`disconnect\`
 * is exposed for graceful-shutdown wiring. \`withTx\` runs a callback in a
 * single connection inside BEGIN/COMMIT (rolled back on throw).
 */
import { Pool, type PoolClient, type QueryResult, type QueryResultRow } from 'pg';

const connectionString =
  process.env.POSTGRES_URL ||
  process.env.DATABASE_URL ||
  'postgres://postgres:postgres@localhost:5432/specverse';

let pool: Pool | null = null;

export function getPool(): Pool {
  if (pool) return pool;
  pool = new Pool({ connectionString });
  return pool;
}

/** Run a parameterised query against the pool.
 *  T defaults to QueryResultRow so callers can pass a row interface. */
export async function query<T extends QueryResultRow = QueryResultRow>(
  text: string,
  params: ReadonlyArray<unknown> = [],
): Promise<QueryResult<T>> {
  return getPool().query<T>(text, params as unknown[]);
}

/** Run a callback inside a transaction. The callback receives a dedicated
 *  client; commit on resolve, rollback on throw. */
export async function withTx<T>(
  fn: (client: PoolClient) => Promise<T>,
): Promise<T> {
  const client = await getPool().connect();
  try {
    await client.query('BEGIN');
    const result = await fn(client);
    await client.query('COMMIT');
    return result;
  } catch (err) {
    await client.query('ROLLBACK');
    throw err;
  } finally {
    client.release();
  }
}

/** Build a comma-separated list of \`"col"\` from an object's keys, plus
 *  matching positional placeholders \`$1, $2, ...\`. Quoted to preserve
 *  case-sensitive identifiers (camelCase columns work without folding). */
function buildPositionals(keys: string[], offset = 0): string {
  return keys.map((_k, i) => '$' + (i + 1 + offset)).join(', ');
}
function quoteCols(keys: string[]): string {
  return keys.map((k) => '"' + k.replace(/"/g, '""') + '"').join(', ');
}

/** INSERT a record into \`table\` and return the inserted row (with any
 *  database-supplied defaults like generated id / createdAt populated). */
export async function insertOne<T extends QueryResultRow = QueryResultRow>(
  table: string,
  record: Record<string, unknown>,
): Promise<T> {
  const keys = Object.keys(record);
  const values = keys.map((k) => record[k]);
  const sql = keys.length === 0
    ? \`INSERT INTO "\${table}" DEFAULT VALUES RETURNING *\`
    : \`INSERT INTO "\${table}" (\${quoteCols(keys)}) VALUES (\${buildPositionals(keys)}) RETURNING *\`;
  const result = await query<T>(sql, values);
  return result.rows[0] as T;
}

/** Bulk-insert many records into \`table\` in one round trip. Returns the
 *  inserted rows. All records must share the same shape. */
export async function insertMany<T extends QueryResultRow = QueryResultRow>(
  table: string,
  records: ReadonlyArray<Record<string, unknown>>,
): Promise<T[]> {
  if (records.length === 0) return [];
  const firstKeys = Object.keys(records[0]!);
  const valuesClauses: string[] = [];
  const flatValues: unknown[] = [];
  for (let i = 0; i < records.length; i++) {
    const row = records[i] as Record<string, unknown>;
    const placeholders = firstKeys.map((_k, j) => '$' + (i * firstKeys.length + j + 1)).join(', ');
    valuesClauses.push('(' + placeholders + ')');
    for (const k of firstKeys) flatValues.push(row[k]);
  }
  const sql = \`INSERT INTO "\${table}" (\${quoteCols(firstKeys)}) VALUES \${valuesClauses.join(', ')} RETURNING *\`;
  const result = await query<T>(sql, flatValues);
  return result.rows;
}

/** SELECT a single row by a field equality. Returns null if not found. */
export async function findOneByField<T extends QueryResultRow = QueryResultRow>(
  table: string,
  field: string,
  value: unknown,
): Promise<T | null> {
  const sql = \`SELECT * FROM "\${table}" WHERE "\${field.replace(/"/g, '""')}" = $1 LIMIT 1\`;
  const result = await query<T>(sql, [value]);
  return result.rows[0] ?? null;
}

/** SELECT a single row matching all (field, value) pairs (AND-ed). */
export async function findOneByFields<T extends QueryResultRow = QueryResultRow>(
  table: string,
  fields: Record<string, unknown>,
): Promise<T | null> {
  const keys = Object.keys(fields);
  if (keys.length === 0) {
    const result = await query<T>(\`SELECT * FROM "\${table}" LIMIT 1\`);
    return result.rows[0] ?? null;
  }
  const where = keys.map((k, i) => '"' + k.replace(/"/g, '""') + '" = $' + (i + 1)).join(' AND ');
  const sql = \`SELECT * FROM "\${table}" WHERE \${where} LIMIT 1\`;
  const result = await query<T>(sql, keys.map((k) => fields[k]));
  return result.rows[0] ?? null;
}

/** SELECT all rows from a table \u2014 equivalent to a Mongo
 *  \`collection.find({}).toArray()\` for the bulk-fan-out auto-create
 *  convention. */
export async function findAll<T extends QueryResultRow = QueryResultRow>(
  table: string,
): Promise<T[]> {
  const result = await query<T>(\`SELECT * FROM "\${table}"\`);
  return result.rows;
}

/** UPDATE columns of the row identified by id. Quotes column names so
 *  camelCase identifiers survive postgres' default lower-case folding. */
export async function updateOneById(
  table: string,
  id: unknown,
  patch: Record<string, unknown>,
): Promise<void> {
  const keys = Object.keys(patch);
  if (keys.length === 0) return;
  const setClause = keys.map((k, i) => '"' + k.replace(/"/g, '""') + '" = $' + (i + 1)).join(', ');
  const sql = \`UPDATE "\${table}" SET \${setClause} WHERE "id" = $\${keys.length + 1}\`;
  await query(sql, [...keys.map((k) => patch[k]), id]);
}

/** DELETE the row identified by id. */
export async function deleteOneById(table: string, id: unknown): Promise<void> {
  await query(\`DELETE FROM "\${table}" WHERE "id" = $1\`, [id]);
}

export async function disconnect(): Promise<void> {
  if (pool) {
    await pool.end();
    pool = null;
  }
}
`;
}
export {
  generatePgClient as default
};
