import { betterAuth } from "better-auth";
import { prismaAdapter } from "better-auth/adapters/prisma";
import { genericOAuth } from "better-auth/plugins";
import type { PrismaClient } from "@prisma/client";

/**
 * Required OIDC environment variables when OIDC is enabled
 */
const REQUIRED_OIDC_ENV_VARS = ["OIDC_ISSUER", "OIDC_CLIENT_ID", "OIDC_CLIENT_SECRET"] as const;

/**
 * Check if OIDC authentication is enabled via environment variable
 */
export function isOidcEnabled(): boolean {
  const enabled = process.env.OIDC_ENABLED;
  return enabled === "true" || enabled === "1";
}

/**
 * Validates OIDC configuration at startup.
 * Throws an error if OIDC is enabled but required environment variables are missing.
 *
 * @throws Error if OIDC is enabled but required vars are missing or empty
 */
export function validateOidcConfig(): void {
  if (!isOidcEnabled()) {
    // OIDC is disabled, no validation needed
    return;
  }

  const missingVars: string[] = [];

  for (const envVar of REQUIRED_OIDC_ENV_VARS) {
    const value = process.env[envVar];
    if (!value || value.trim() === "") {
      missingVars.push(envVar);
    }
  }

  if (missingVars.length > 0) {
    throw new Error(
      `OIDC authentication is enabled (OIDC_ENABLED=true) but required environment variables are missing or empty: ${missingVars.join(", ")}. ` +
        `Either set these variables or disable OIDC by setting OIDC_ENABLED=false.`
    );
  }

  // Additional validation: OIDC_ISSUER should end with a trailing slash for proper discovery URL
  const issuer = process.env.OIDC_ISSUER;
  if (issuer && !issuer.endsWith("/")) {
    throw new Error(
      `OIDC_ISSUER must end with a trailing slash (/). Current value: "${issuer}". ` +
        `The discovery URL is constructed by appending ".well-known/openid-configuration" to the issuer.`
    );
  }
}

/**
 * Get OIDC plugins configuration.
 * Returns empty array if OIDC is disabled, otherwise returns configured OAuth plugin.
 */
function getOidcPlugins(): ReturnType<typeof genericOAuth>[] {
  if (!isOidcEnabled()) {
    return [];
  }

  return [
    genericOAuth({
      config: [
        {
          providerId: "authentik",
          clientId: process.env.OIDC_CLIENT_ID ?? "",
          clientSecret: process.env.OIDC_CLIENT_SECRET ?? "",
          discoveryUrl: `${process.env.OIDC_ISSUER ?? ""}.well-known/openid-configuration`,
          scopes: ["openid", "profile", "email"],
        },
      ],
    }),
  ];
}

export function createAuth(prisma: PrismaClient) {
  // Validate OIDC configuration at startup - fail fast if misconfigured
  validateOidcConfig();

  return betterAuth({
    database: prismaAdapter(prisma, {
      provider: "postgresql",
    }),
    emailAndPassword: {
      enabled: true, // Enable for now, can be disabled later
    },
    plugins: [...getOidcPlugins()],
    session: {
      expiresIn: 60 * 60 * 24, // 24 hours
      updateAge: 60 * 60 * 24, // 24 hours
    },
    trustedOrigins: [
      process.env.NEXT_PUBLIC_APP_URL ?? "http://localhost:3000",
      "http://localhost:3001", // API origin (dev)
      "https://app.mosaicstack.dev", // Production web
      "https://api.mosaicstack.dev", // Production API
    ],
  });
}

export type Auth = ReturnType<typeof createAuth>;
