import { PrismaPg } from '@prisma/adapter-pg';
import { PrismaClient } from './generated/prisma/client';

export { PrismaClient };
export type Db = PrismaClient;

const DEFAULT_DEV_URL = 'postgresql://pintrush:pintrush@localhost:54329/pintrush';
const SCHEMA_NAME = /^[A-Za-z_][A-Za-z0-9_]{0,62}$/;

/**
 * Split Prisma's `?schema=` URL parameter off the connection string. node-postgres does not know it,
 * so the adapter gets it as an option (for generated SQL) and the connection gets a matching
 * search_path (for raw SQL), keeping both pointed at the same Postgres schema.
 */
function splitSchema(connectionString: string): { url: string; schema: string | null } {
  let parsed: URL;
  try {
    parsed = new URL(connectionString);
  } catch {
    return { url: connectionString, schema: null };
  }
  const schema = parsed.searchParams.get('schema');
  if (schema === null) return { url: connectionString, schema: null };
  if (!SCHEMA_NAME.test(schema)) throw new Error(`DATABASE_URL has an invalid schema name: ${schema}`);
  parsed.searchParams.delete('schema');
  return { url: parsed.toString(), schema };
}

/** Create a new Prisma client. Prefer `getDb()` in app code so one pool is shared per process. */
export function createDb(connectionString: string = process.env.DATABASE_URL ?? DEFAULT_DEV_URL): PrismaClient {
  const { url, schema } = splitSchema(connectionString);
  const adapter = schema
    ? new PrismaPg({ connectionString: url, options: `-c search_path=${schema}` }, { schema })
    : new PrismaPg({ connectionString: url });
  return new PrismaClient({ adapter });
}

const globalForDb = globalThis as unknown as { __pintrushDb?: PrismaClient };

/** Process-wide shared client (survives Next.js hot reloads in dev). */
export function getDb(): PrismaClient {
  if (!globalForDb.__pintrushDb) globalForDb.__pintrushDb = createDb();
  return globalForDb.__pintrushDb;
}
