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 `archived_at` to now.
 * The table must have an `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> {
  await db
    .update(table)
    .set({ archived_at: sql`now()` } as Record<string, unknown>)
    .where(eq(idColumn, id));
}

/**
 * Restores a soft-deleted record by clearing `archived_at`.
 * The table must have an `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({ archived_at: null } as Record<string, unknown>)
    .where(eq(idColumn, id));
}
