/**
 * Kết nối cơ sở dữ liệu.
 *
 * Cùng một schema chạy trên hai chế độ, chọn bằng biến môi trường DB_DRIVER:
 *
 *   pglite → Postgres nhúng, dữ liệu nằm trong thư mục .pgdata của dự án.
 *            Không cần cài PostgreSQL, dùng cho máy dev và bản demo cho khách.
 *   pg     → Postgres thật (VPS, Neon, Supabase, RDS). Dùng cho production.
 *
 * Chuyển từ demo sang production chỉ là đổi hai dòng trong .env.local, không
 * phải sửa một dòng code truy vấn nào.
 */
import * as schema from "./schema";

export type Database = ReturnType<typeof createDatabase>;

function createDatabase() {
  const driver = process.env.DB_DRIVER ?? "pglite";

  if (driver === "pg") {
    const url = process.env.DATABASE_URL;
    if (!url) {
      throw new Error("DB_DRIVER=pg nhưng thiếu DATABASE_URL trong biến môi trường.");
    }
    // eslint-disable-next-line @typescript-eslint/no-require-imports
    const { Pool } = require("pg") as typeof import("pg");
    // eslint-disable-next-line @typescript-eslint/no-require-imports
    const { drizzle } = require("drizzle-orm/node-postgres") as typeof import("drizzle-orm/node-postgres");
    // Số kết nối tối đa tới PostgreSQL: gói hosting dùng chung thường giới hạn số kết nối đồng thời — hạ PG_POOL_MAX (ví dụ 4) nếu gặp lỗi "too many connections".
    const pool = new Pool({ connectionString: url, max: Number(process.env.PG_POOL_MAX) || 10 });
    return drizzle(pool, { schema });
  }

  // eslint-disable-next-line @typescript-eslint/no-require-imports
  const { PGlite } = require("@electric-sql/pglite") as typeof import("@electric-sql/pglite");
  // eslint-disable-next-line @typescript-eslint/no-require-imports
  const { drizzle } = require("drizzle-orm/pglite") as typeof import("drizzle-orm/pglite");
  const client = new PGlite(process.env.PGLITE_DIR ?? "./.pgdata");
  return drizzle(client, { schema });
}

/**
 * Giữ một kết nối duy nhất cho cả tiến trình, kể cả qua các lần hot-reload của
 * Next.js trong chế độ dev — nếu không, mỗi lần sửa file lại mở thêm một instance
 * PGlite trên cùng thư mục dữ liệu.
 */
const globalForDb = globalThis as unknown as { __crmDb?: Database };

/**
 * Kết nối được tạo ở lần truy vấn đầu tiên, không phải lúc import module.
 *
 * `next build` nạp toàn bộ module trong nhiều tiến trình worker để phân tích.
 * Nếu kết nối mở ngay khi import, mỗi worker sẽ mở một instance PGlite trên cùng
 * thư mục `.pgdata` và làm hỏng dữ liệu — lỗi này đã xảy ra thật trong quá trình
 * phát triển. Toàn bộ trang đều là server-rendered động nên không trang nào cần
 * dữ liệu lúc build; hoãn kết nối tới lần dùng đầu tiên là đủ để tránh hẳn.
 */
export const db: Database = new Proxy({} as Database, {
  get(_target, property, receiver) {
    const instance = (globalForDb.__crmDb ??= createDatabase());
    const value = Reflect.get(instance as object, property, receiver);
    return typeof value === "function" ? value.bind(instance) : value;
  },
});

export { schema };
