import { z } from 'zod'

// Toute la configuration passe par les variables d'environnement, validées au démarrage.
// Une variable manquante ou invalide fait échouer le démarrage : jamais de valeur par défaut pour un secret.
// Ce schéma est complété à chaque phase (Discord OAuth, JWT, Stripe...), cf. .env.example.

const dbEnvSchema = z.object({
  DB_HOST: z.string().min(1),
  DB_PORT: z.coerce.number().int().min(1).max(65535),
  DB_USER: z.string().min(1),
  DB_PASSWORD: z.string().min(1),
  DB_NAME: z.string().min(1),
})

const envSchema = dbEnvSchema.extend({
  NODE_ENV: z.enum(['development', 'production']),
  API_HOST: z.string().min(1),
  API_PORT: z.coerce.number().int().min(1).max(65535),
  // IP (ou CIDR) du reverse proxy Apache autorisé à fournir X-Forwarded-For. "false" = aucun proxy de confiance.
  TRUST_PROXY: z.string().min(1),
  PUBLIC_SITE_URL: z.url(),
})

export type DbConfig = z.infer<typeof dbEnvSchema>
export type Config = z.infer<typeof envSchema>

function parseEnv<T extends z.ZodType>(schema: T, env: NodeJS.ProcessEnv): z.infer<T> {
  const result = schema.safeParse(env)
  if (!result.success) {
    // On n'affiche que les noms des variables fautives, jamais leurs valeurs (secrets).
    const issues = result.error.issues.map((issue) => `  - ${issue.path.join('.')}: ${issue.message}`)
    throw new Error(`Configuration invalide :\n${issues.join('\n')}`)
  }
  return result.data
}

export function loadConfig(env: NodeJS.ProcessEnv = process.env): Config {
  return parseEnv(envSchema, env)
}

// Utilisé par l'outil de migration, qui n'a besoin que de l'accès à la base.
export function loadDbConfig(env: NodeJS.ProcessEnv = process.env): DbConfig {
  return parseEnv(dbEnvSchema, env)
}
