import { eq, sql } from 'drizzle-orm';
import type { PgTable, PgColumn } from 'drizzle-orm/pg-core';
import { db } from './index';

/**
 * Drizzle transaction client type - the argument shape `db.transaction`'s
 * callback receives. Exported so service helpers that take a `tx`
 * parameter can spell the type instead of falling back to `any`.
 */
export type Tx = Parameters<Parameters<typeof db.transaction>[0]>[0];

/**
 * Wraps a database operation in a transaction.
 * Rolls back automatically on error.
 *
 * @example
 * const result = await withTransaction(async (tx) => {
 *   await tx.insert(clients).values({ ... });
 *   await tx.insert(interests).values({ ... });
 *   return result;
 * });
 */
export async function withTransaction<T>(callback: (tx: typeof db) => Promise<T>): Promise<T> {
  return db.transaction(callback as unknown as Parameters<typeof db.transaction>[0]) as Promise<T>;
}

/**
 * Soft-deletes a record by setting `archivedAt` to now.
 * The table must have an `archivedAt` JS property mapping to the
 * `archived_at` column.
 *
 * @example
 * await softDelete(clients, clients.id, clientId);
 */
export async function softDelete<TTable extends PgTable>(
  table: TTable,
  idColumn: PgColumn,
  id: string,
): Promise<void> {
  // Drizzle's `.set()` API expects the JS property name (`archivedAt`),
  // not the snake-case column name. The previous version passed
  // `{ archived_at: ... }` which silently produced an empty SET clause
  // (Drizzle skipped the unknown property) → `UPDATE ... where ...`
  // syntax error from Postgres. Caught by QA: archive an interest
  // with a berth attached → 500. Same fix in restore() below.
  await db
    .update(table)
    .set({ archivedAt: sql`now()` } as Record<string, unknown>)
    .where(eq(idColumn, id));
}

/**
 * Restores a soft-deleted record by clearing `archivedAt`.
 * The table must have an `archivedAt` JS property mapping to the
 * `archived_at` column.
 *
 * @example
 * await restore(clients, clients.id, clientId);
 */
export async function restore<TTable extends PgTable>(
  table: TTable,
  idColumn: PgColumn,
  id: string,
): Promise<void> {
  await db
    .update(table)
    .set({ archivedAt: null } as Record<string, unknown>)
    .where(eq(idColumn, id));
}
