import * as schema from "./schema";
import { drizzle as drizzlePg } from "drizzle-orm/postgres-js";
import { drizzle as drizzlePglite } from "drizzle-orm/pglite";
import postgres from "postgres";
import { PGlite } from "@electric-sql/pglite";

/**
 * Connexion DB :
 * - Si DATABASE_URL est défini : postgres-js (vrai Postgres, dev/staging/prod).
 * - Sinon : PGlite (Postgres en WASM, file-based dans ./pgdata).
 *
 * Schema unique partagé : `pg-core` Drizzle, compatible avec les deux.
 *
 * Initialisation lazy (à la première utilisation) pour que le build
 * Next.js n'échoue pas si DATABASE_URL n'est pas set au moment du build.
 */

const usePostgres =
  typeof process.env.DATABASE_URL === "string" &&
  process.env.DATABASE_URL.length > 0;

// Type de la DB dev — sert aussi à typer la DB prod (les schemas sont identiques).
type SocialexDb = ReturnType<typeof buildDevDb>;

declare global {
  // eslint-disable-next-line no-var
  var __socialex_db: SocialexDb | undefined;
}

function buildPgDb(): SocialexDb {
  const client = postgres(process.env.DATABASE_URL!, {
    max: 10,
    idle_timeout: 20,
  });
  // Cast pour aligner les types : les deux drivers exposent la même API
  // côté Drizzle (mêmes méthodes select/insert/etc avec le même schema).
  return drizzlePg(client, { schema }) as unknown as SocialexDb;
}

function buildDevDb() {
  const client = new PGlite("./pgdata");
  return drizzlePglite(client, { schema });
}

function getDb(): SocialexDb {
  if (globalThis.__socialex_db) return globalThis.__socialex_db;
  const built = usePostgres ? buildPgDb() : buildDevDb();
  globalThis.__socialex_db = built;
  return built;
}

// Proxy lazy : le client réel n'est instancié qu'à la première propriété accédée.
// Ça évite de planter au build Next quand DATABASE_URL n'est pas set.
export const db = new Proxy({} as SocialexDb, {
  get(_target, prop) {
    const real = getDb();
    const value = (real as unknown as Record<string | symbol, unknown>)[
      prop as string
    ];
    if (typeof value === "function") return value.bind(real);
    return value;
  },
});

export type DB = SocialexDb;
export { schema };
