import { drizzle } from "drizzle-orm/node-postgres";
import { existsSync } from "node:fs";
import { readFileSync } from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
import pg from "pg";
import * as schema from "./schema";

const { Pool } = pg;

function parsePositiveInteger(
  value: string | undefined,
  fallback: number,
  minimum = 1,
) {
  if (!value) return fallback;
  const parsed = Number(value.trim());
  if (!Number.isFinite(parsed)) return fallback;
  const normalized = Math.floor(parsed);
  return normalized >= minimum ? normalized : fallback;
}

if (!process.env.DATABASE_URL) {
  const nodeEnv = process.env.NODE_ENV ?? "development";
  const moduleDir = path.dirname(fileURLToPath(import.meta.url));
  const repoRoot = path.resolve(moduleDir, "../../..");
  const envPath = path.resolve(repoRoot, ".env");

  if (nodeEnv !== "production" && existsSync(envPath)) {
    const raw = readFileSync(envPath, "utf8");
    for (const line of raw.split(/\r?\n/)) {
      const trimmed = line.trim();
      if (!trimmed || trimmed.startsWith("#")) continue;
      const eqIndex = trimmed.indexOf("=");
      if (eqIndex <= 0) continue;

      const key = trimmed.slice(0, eqIndex).trim();
      let value = trimmed.slice(eqIndex + 1).trim();

      if (
        (value.startsWith('"') && value.endsWith('"')) ||
        (value.startsWith("'") && value.endsWith("'"))
      ) {
        value = value.slice(1, -1);
      }

      if (process.env[key] === undefined) {
        process.env[key] = value;
      }
    }
  }
}

const databaseUrl = process.env.DATABASE_URL;
const nodeEnv = process.env.NODE_ENV ?? "development";

if (!databaseUrl) {
  throw new Error(
    "DATABASE_URL must be set. Did you forget to provision a database?",
  );
}

const poolMax = parsePositiveInteger(
  process.env.DB_POOL_MAX,
  nodeEnv === "production" ? 5 : 10,
);
const connectionTimeoutMillis = parsePositiveInteger(
  process.env.DB_CONNECTION_TIMEOUT_MS,
  10_000,
);
const idleTimeoutMillis = parsePositiveInteger(
  process.env.DB_IDLE_TIMEOUT_MS,
  10_000,
);
const maxLifetimeSeconds = parsePositiveInteger(
  process.env.DB_MAX_LIFETIME_SECONDS,
  300,
);
const applicationName =
  process.env.DB_APPLICATION_NAME?.trim() ||
  `wwn-${nodeEnv === "production" ? "prod" : "dev"}`;

export const pool = new Pool({
  connectionString: databaseUrl,
  max: poolMax,
  connectionTimeoutMillis,
  idleTimeoutMillis,
  maxLifetimeSeconds,
  application_name: applicationName,
  keepAlive: true,
});
export const db = drizzle(pool, { schema });

export * from "./schema";
