import { z } from "zod";

const schema = z.object({
  DATABASE_URL: z.string().min(1).startsWith("postgres"),
  NEXTAUTH_SECRET: z.string().min(32),
  NEXTAUTH_URL: z.string().url(),
  APPROVAL_TOKEN_SECRET: z.string().min(32),
  ADMIN_NOTIFY_EMAILS: z.string().min(3),
  EMAIL_FROM: z.string().min(3),
  RESEND_API_KEY: z.string().optional().default(""),
  NEXT_PUBLIC_SANITY_PROJECT_ID: z.string().optional(),
  NEXT_PUBLIC_SANITY_DATASET: z.string().optional().default("production"),
  NEXT_PUBLIC_SANITY_API_VERSION: z.string().optional().default("2026-03-01"),
  SANITY_API_READ_TOKEN: z.string().optional(),
  SANITY_WEBHOOK_SECRET: z.string().optional(),
  NEXT_PUBLIC_SANITY_PREVIEW_SECRET: z.string().optional(),
  CRON_SECRET: z.string().optional(),
  // Google OAuth — optional. When both are set, the login page shows a
  // "Continue with Google" button; signIn callback still enforces the
  // vetted-member gate (email must match an `active` users row).
  GOOGLE_CLIENT_ID: z.string().optional().default(""),
  GOOGLE_CLIENT_SECRET: z.string().optional().default(""),
});

export type AppEnv = {
  databaseUrl: string;
  nextAuthSecret: string;
  nextAuthUrl: string;
  approvalTokenSecret: string;
  adminNotifyEmails: string[];
  emailFrom: string;
  resendApiKey: string;
  sanityProjectId: string | undefined;
  sanityDataset: string;
  sanityApiVersion: string;
  sanityApiReadToken: string | undefined;
  sanityWebhookSecret: string | undefined;
  sanityPreviewSecret: string | undefined;
  googleClientId: string;
  googleClientSecret: string;
  googleAuthEnabled: boolean;
};

let cached: AppEnv | null = null;

export function loadEnv(): AppEnv {
  if (cached) return cached;
  const parsed = schema.parse(process.env);
  cached = {
    databaseUrl: parsed.DATABASE_URL,
    nextAuthSecret: parsed.NEXTAUTH_SECRET,
    nextAuthUrl: parsed.NEXTAUTH_URL,
    approvalTokenSecret: parsed.APPROVAL_TOKEN_SECRET,
    adminNotifyEmails: parsed.ADMIN_NOTIFY_EMAILS.split(",")
      .map((s) => s.trim())
      .filter(Boolean),
    emailFrom: parsed.EMAIL_FROM,
    resendApiKey: parsed.RESEND_API_KEY ?? "",
    sanityProjectId:
      parsed.NEXT_PUBLIC_SANITY_PROJECT_ID &&
      parsed.NEXT_PUBLIC_SANITY_PROJECT_ID.length > 0
        ? parsed.NEXT_PUBLIC_SANITY_PROJECT_ID
        : undefined,
    sanityDataset: parsed.NEXT_PUBLIC_SANITY_DATASET,
    sanityApiVersion: parsed.NEXT_PUBLIC_SANITY_API_VERSION,
    sanityApiReadToken:
      parsed.SANITY_API_READ_TOKEN && parsed.SANITY_API_READ_TOKEN.length > 0
        ? parsed.SANITY_API_READ_TOKEN
        : undefined,
    sanityWebhookSecret:
      parsed.SANITY_WEBHOOK_SECRET && parsed.SANITY_WEBHOOK_SECRET.length > 0
        ? parsed.SANITY_WEBHOOK_SECRET
        : undefined,
    sanityPreviewSecret:
      parsed.NEXT_PUBLIC_SANITY_PREVIEW_SECRET &&
      parsed.NEXT_PUBLIC_SANITY_PREVIEW_SECRET.length > 0
        ? parsed.NEXT_PUBLIC_SANITY_PREVIEW_SECRET
        : undefined,
    googleClientId: parsed.GOOGLE_CLIENT_ID ?? "",
    googleClientSecret: parsed.GOOGLE_CLIENT_SECRET ?? "",
    googleAuthEnabled:
      (parsed.GOOGLE_CLIENT_ID ?? "").length > 0 &&
      (parsed.GOOGLE_CLIENT_SECRET ?? "").length > 0,
  };
  return cached;
}

export function resetEnvCacheForTests(): void {
  cached = null;
}
