import { z } from "zod"

const urlField = () =>
  z.preprocess(
    (value) => (typeof value === "string" ? value.trim() || undefined : value),
    z.string().url().optional()
  )

const stringField = () =>
  z.preprocess(
    (value) => (typeof value === "string" ? value.trim() || undefined : value),
    z.string().min(1).optional()
  )

const envSchema = z.object({
  BETTER_AUTH_SECRET: stringField().or(z.literal("")).optional(),
  BETTER_AUTH_URL: urlField().or(z.literal("")).optional(),
  NEXT_PUBLIC_CONVEX_URL: urlField().or(z.literal("")).optional(),
  CONVEX_INTERNAL_URL: urlField().or(z.literal("")).optional(),
  DATABASE_URL: stringField().or(z.literal("")).optional(),
  NEXT_PUBLIC_APP_URL: urlField().or(z.literal("")).optional(),
  MACHINE_PROVISIONING_SECRET: z.string().optional(),
  MACHINE_TOKEN_TTL_MS: z.coerce.number().optional(),
  FLEET_SYNC_SECRET: z.string().optional(),
  SMTP_ADDRESS: z.string().optional(),
  SMTP_PORT: z.coerce.number().optional(),
  SMTP_DOMAIN: z.string().optional(),
  SMTP_USERNAME: z.string().optional(),
  SMTP_PASSWORD: z.string().optional(),
  SMTP_AUTHENTICATION: z.string().optional(),
  SMTP_ENABLE_STARTTLS_AUTO: z.string().optional(),
  SMTP_TLS: z.string().optional(),
  MAILER_SENDER_EMAIL: z.string().optional(),
  REPORTS_CRON_SECRET: z.string().optional(),
  INTERNAL_HEALTH_TOKEN: z.string().optional(),
  REPORTS_CRON_BASE_URL: urlField().or(z.literal("")).optional(),
  ARCHIVE_DIR: stringField().or(z.literal("")).optional(),
})

const parsed = envSchema.safeParse(process.env)

if (!parsed.success) {
  console.error("Failed to parse environment variables", parsed.error.flatten().fieldErrors)
  throw new Error("Invalid environment configuration")
}

const isBuildPhase = process.env.NEXT_PHASE === "phase-production-build"

function resolveSecret(value: string | undefined, key: string) {
  if (value && value.length > 0) return value
  const fallback = isBuildPhase ? `build-placeholder-${key.toLowerCase()}` : `dev-${key.toLowerCase()}`
  if (process.env.NODE_ENV === "production" && !isBuildPhase) {
    throw new Error(`${key} must be set in production runtime environment`)
  }
  if (!isBuildPhase) {
    console.warn(`ENV ${key} not set; using fallback value only for development.`)
  }
  return fallback
}

export const env = {
  BETTER_AUTH_SECRET: resolveSecret(parsed.data.BETTER_AUTH_SECRET, "BETTER_AUTH_SECRET"),
  BETTER_AUTH_URL: parsed.data.BETTER_AUTH_URL ?? parsed.data.NEXT_PUBLIC_APP_URL ?? "http://localhost:3000",
  NEXT_PUBLIC_CONVEX_URL: parsed.data.NEXT_PUBLIC_CONVEX_URL,
  CONVEX_INTERNAL_URL: parsed.data.CONVEX_INTERNAL_URL,
  DATABASE_URL: parsed.data.DATABASE_URL,
  NEXT_PUBLIC_APP_URL: parsed.data.NEXT_PUBLIC_APP_URL,
  MACHINE_PROVISIONING_SECRET: parsed.data.MACHINE_PROVISIONING_SECRET,
  MACHINE_TOKEN_TTL_MS: parsed.data.MACHINE_TOKEN_TTL_MS,
  FLEET_SYNC_SECRET: parsed.data.FLEET_SYNC_SECRET,
  REPORTS_CRON_SECRET: parsed.data.REPORTS_CRON_SECRET,
  INTERNAL_HEALTH_TOKEN: parsed.data.INTERNAL_HEALTH_TOKEN,
  REPORTS_CRON_BASE_URL: parsed.data.REPORTS_CRON_BASE_URL,
  ARCHIVE_DIR: parsed.data.ARCHIVE_DIR ?? "./archives",
  SMTP: parsed.data.SMTP_ADDRESS && parsed.data.SMTP_USERNAME && parsed.data.SMTP_PASSWORD
    ? {
        host: parsed.data.SMTP_ADDRESS,
        port: parsed.data.SMTP_PORT ?? 465,
        domain: parsed.data.SMTP_DOMAIN,
        username: parsed.data.SMTP_USERNAME,
        password: parsed.data.SMTP_PASSWORD,
        tls: (parsed.data.SMTP_TLS ?? "true").toLowerCase() === "true",
        starttls: (parsed.data.SMTP_ENABLE_STARTTLS_AUTO ?? "false").toLowerCase() === "true",
        auth: parsed.data.SMTP_AUTHENTICATION ?? "login",
        from: parsed.data.MAILER_SENDER_EMAIL ?? "no-reply@example.com",
      }
    : null,
}
