/**
 * The single Knex instance for the whole app. Import `db` from here; never call
 * `knex()` anywhere else.
 *
 * Mirrors messagepal-backend's src/db/sequelize.js: one lazy singleton, and the
 * schema is owned entirely by migrations — nothing here ever creates tables.
 */
import knex, { type Knex } from 'knex';
import knexConfig from './knex-config';

export const db: Knex = knex(knexConfig);

/** Close the pool during graceful shutdown (src/server.ts). */
export async function destroyDb(): Promise<void> {
  await db.destroy();
}

export interface DbPing {
  ok: boolean;
  latencyMs: number;
  error?: string;
}

/**
 * `SELECT 1` with a hard timeout, for /health. A wedged pool must not hang the
 * health check past a couple of seconds — an uptime monitor reads that as down,
 * which is the correct signal.
 */
export async function pingDb(timeoutMs = 2000): Promise<DbPing> {
  const started = Date.now();
  try {
    await Promise.race([
      db.raw('select 1'),
      new Promise((_resolve, reject) =>
        setTimeout(() => reject(new Error(`db ping timed out after ${timeoutMs}ms`)), timeoutMs),
      ),
    ]);
    return { ok: true, latencyMs: Date.now() - started };
  } catch (err) {
    return {
      ok: false,
      latencyMs: Date.now() - started,
      error: err instanceof Error ? err.message : String(err),
    };
  }
}
