type EnvironmentVariables = {
  PORT?: string;
  DATABASE_URL?: string;
  JWT_ACCESS_SECRET?: string;
  JWT_REFRESH_SECRET?: string;
  JWT_ACCESS_EXPIRES_IN?: string;
  JWT_REFRESH_EXPIRES_IN?: string;
  CORS_ORIGIN?: string;
  NODE_ENV?: string;
  EMAIL_ENABLED?: string;
  EMAIL_PROVIDER?: string;
  BREVO_API_KEY?: string;
  EMAIL_FROM_ADDRESS?: string;
  EMAIL_FROM_NAME?: string;
  EMAIL_REPLY_TO?: string;
  API_PUBLIC_URL?: string;
  FRONTEND_URL?: string;
  PASSWORD_SETUP_TOKEN_TTL_HOURS?: string;
};

export function validateEnv(config: EnvironmentVariables) {
  const requiredKeys: Array<keyof EnvironmentVariables> = [
    'DATABASE_URL',
    'JWT_ACCESS_SECRET',
    'JWT_REFRESH_SECRET',
    'JWT_ACCESS_EXPIRES_IN',
    'JWT_REFRESH_EXPIRES_IN',
  ];

  for (const key of requiredKeys) {
    if (!config[key]) {
      throw new Error(`Missing required environment variable: ${key}`);
    }
  }

  const emailEnabled = config.EMAIL_ENABLED?.trim().toLowerCase() ?? 'false';
  if (!['true', 'false'].includes(emailEnabled)) {
    throw new Error('EMAIL_ENABLED must be either true or false.');
  }

  if (config.EMAIL_PROVIDER && config.EMAIL_PROVIDER !== 'brevo') {
    throw new Error('EMAIL_PROVIDER must be brevo.');
  }

  if (emailEnabled === 'true') {
    for (const key of [
      'BREVO_API_KEY',
      'EMAIL_FROM_ADDRESS',
      'API_PUBLIC_URL',
      'FRONTEND_URL',
    ] as const) {
      if (!config[key]?.trim()) {
        throw new Error(`Missing required environment variable: ${key}`);
      }
    }

    try {
      new URL(config.API_PUBLIC_URL!);
    } catch {
      throw new Error('API_PUBLIC_URL must be a valid absolute URL.');
    }

    try {
      new URL(config.FRONTEND_URL!);
    } catch {
      throw new Error('FRONTEND_URL must be a valid absolute URL.');
    }
  }

  if (config.PASSWORD_SETUP_TOKEN_TTL_HOURS) {
    const tokenTtlHours = Number(config.PASSWORD_SETUP_TOKEN_TTL_HOURS);
    if (!Number.isInteger(tokenTtlHours) || tokenTtlHours < 1 || tokenTtlHours > 168) {
      throw new Error('PASSWORD_SETUP_TOKEN_TTL_HOURS must be an integer between 1 and 168.');
    }
  }

  return config;
}
