import { MongoClient, Db } from "mongodb";

/**
 * Serverless-safe MongoDB client.
 *
 * A single MongoClient (and its connection pool) is cached on `globalThis` so
 * that, on Vercel/serverless, warm invocations and Next.js dev hot-reloads reuse
 * one pool instead of opening a new connection on every request (which would
 * exhaust Atlas connection limits — "connection storms"). The driver manages the
 * pool internally; we only ever hold one client promise per process.
 *
 * Server-only: this module reads MONGODB_URI (a secret) and must never be
 * imported into client components. It is used exclusively by server code
 * (route handlers, server actions, scripts).
 */

const DEFAULT_DB_NAME = "quto";

declare global {
  var __qutoMongoClientPromise: Promise<MongoClient> | undefined;
}

function clientPromise(): Promise<MongoClient> {
  const uri = process.env.MONGODB_URI;
  if (!uri) {
    throw new MongoNotConfiguredError();
  }
  if (!global.__qutoMongoClientPromise) {
    const client = new MongoClient(uri, {
      maxPoolSize: 10,
      minPoolSize: 0,
    });
    global.__qutoMongoClientPromise = client.connect();
  }
  return global.__qutoMongoClientPromise;
}

/** Thrown when MONGODB_URI is absent, so callers can distinguish config errors. */
export class MongoNotConfiguredError extends Error {
  constructor() {
    super("MONGODB_URI is not set. Configure it in .env / .env.local / Vercel env.");
    this.name = "MongoNotConfiguredError";
  }
}

export function isMongoConfigured(): boolean {
  return Boolean(process.env.MONGODB_URI);
}

/**
 * Returns the application database. The database name comes from MONGODB_DB, or
 * the database embedded in the connection string (e.g. /quto), or DEFAULT_DB_NAME.
 */
export async function getDb(): Promise<Db> {
  const client = await clientPromise();
  if (process.env.MONGODB_DB?.trim()) {
    return client.db(process.env.MONGODB_DB.trim());
  }
  const defaultDb = client.db();
  if (defaultDb.databaseName && defaultDb.databaseName !== "test") {
    return defaultDb;
  }
  return client.db(DEFAULT_DB_NAME);
}
