/**
 * PostgreSQL database client with connection pooling
 */

import { Pool, PoolConfig, QueryResult, QueryResultRow } from 'pg';

// Re-export types for use in other modules
export type { QueryResult, QueryResultRow };

export interface DatabaseConfig {
  connectionString?: string;
  host?: string;
  port?: number;
  database?: string;
  user?: string;
  password?: string;
  max?: number;
  idleTimeoutMillis?: number;
  connectionTimeoutMillis?: number;
}

/**
 * Create a PostgreSQL connection pool
 */
export function createPool(config: DatabaseConfig): Pool {
  const poolConfig: PoolConfig = {
    connectionString: config.connectionString,
    host: config.host,
    port: config.port,
    database: config.database,
    user: config.user,
    password: config.password,
    max: config.max || 20,
    idleTimeoutMillis: config.idleTimeoutMillis || 30000,
    connectionTimeoutMillis: config.connectionTimeoutMillis || 2000,
  };

  return new Pool(poolConfig);
}

/**
 * Default database pool instance
 */
let defaultPool: Pool | null = null;

/**
 * Get or create the default database pool
 */
export function getPool(config?: DatabaseConfig): Pool {
  if (!defaultPool) {
    if (!config) {
      throw new Error('Database configuration required for first pool creation');
    }
    defaultPool = createPool(config);
  }
  return defaultPool;
}

/**
 * Execute a query
 */
export async function query<T extends QueryResultRow = QueryResultRow>(
  text: string,
  params?: unknown[]
): Promise<QueryResult<T>> {
  if (!defaultPool) {
    throw new Error('Database pool not initialized. Call getPool() with configuration first.');
  }
  return defaultPool.query<T>(text, params);
}

/**
 * Close the database pool
 */
export async function closePool(): Promise<void> {
  if (defaultPool) {
    await defaultPool.end();
    defaultPool = null;
  }
}

/**
 * Health check for database connection
 */
export async function healthCheck(): Promise<boolean> {
  try {
    const pool = getPool();
    await pool.query('SELECT 1');
    return true;
  } catch {
    return false;
  }
}

