/**
 * Environment Configuration
 * Agent 4: Production Deployment
 *
 * Validates and exports environment variables with type safety.
 * Throws errors in production if required variables are missing.
 */

type LogLevel = 'error' | 'warn' | 'info' | 'debug' | 'trace';
type LogFormat = 'json' | 'pretty';
type PrivacyMode = 'standard' | 'enhanced' | 'maximum';
type LocationObfuscation = 'none' | 'fuzzy' | 'region' | 'hidden';
type StorageProvider = 'local' | 's3' | 'r2' | 'minio';

interface EnvConfig {
  // Application
  nodeEnv: 'development' | 'production' | 'test';
  port: number;
  apiUrl: string;
  appName: string;

  // Database
  databaseUrl: string;
  dbHost: string;
  dbPort: number;
  dbUser: string;
  dbPassword: string;
  dbName: string;

  // Redis
  redisUrl: string;
  redisHost: string;
  redisPort: number;

  // Authentication
  nextAuthUrl: string;
  nextAuthSecret: string;
  githubClientId?: string;
  githubClientSecret?: string;
  googleClientId?: string;
  googleClientSecret?: string;

  // Sentry
  sentryDsn?: string;
  sentryOrg?: string;
  sentryProject?: string;
  sentryAuthToken?: string;

  // Logging
  logLevel: LogLevel;
  logFormat: LogFormat;

  // Monitoring
  prometheusEnabled: boolean;
  metricsPort: number;

  // Plants.net
  plantsNetApiKey?: string;

  // Tor
  torEnabled: boolean;
  torSocksHost: string;
  torSocksPort: number;
  torControlPort: number;
  torHiddenServiceDir: string;

  // Privacy
  defaultPrivacyMode: PrivacyMode;
  allowAnonymousRegistration: boolean;
  locationObfuscationDefault: LocationObfuscation;

  // Storage
  storageProvider: StorageProvider;
  s3Bucket?: string;
  s3Region?: string;
  s3AccessKeyId?: string;
  s3SecretAccessKey?: string;
  s3Endpoint?: string;

  // Email
  smtpHost: string;
  smtpPort: number;
  smtpUser?: string;
  smtpPassword?: string;
  smtpFrom: string;

  // Rate Limiting
  rateLimitWindowMs: number;
  rateLimitMaxRequests: number;

  // Security
  corsOrigins: string[];
  cspReportUri?: string;

  // Feature Flags
  isProduction: boolean;
  isDevelopment: boolean;
  isTest: boolean;
}

function getEnvString(key: string, defaultValue?: string): string {
  const value = process.env[key] ?? defaultValue;
  if (value === undefined) {
    if (process.env.NODE_ENV === 'production') {
      throw new Error(`Missing required environment variable: ${key}`);
    }
    return '';
  }
  return value;
}

function getEnvNumber(key: string, defaultValue: number): number {
  const value = process.env[key];
  if (value === undefined) {
    return defaultValue;
  }
  const parsed = parseInt(value, 10);
  if (isNaN(parsed)) {
    throw new Error(`Environment variable ${key} must be a number, got: ${value}`);
  }
  return parsed;
}

function getEnvBoolean(key: string, defaultValue: boolean): boolean {
  const value = process.env[key];
  if (value === undefined) {
    return defaultValue;
  }
  return value.toLowerCase() === 'true' || value === '1';
}

function getEnvArray(key: string, defaultValue: string[] = []): string[] {
  const value = process.env[key];
  if (value === undefined || value === '') {
    return defaultValue;
  }
  return value.split(',').map((s) => s.trim()).filter(Boolean);
}

function validateLogLevel(value: string): LogLevel {
  const validLevels: LogLevel[] = ['error', 'warn', 'info', 'debug', 'trace'];
  if (!validLevels.includes(value as LogLevel)) {
    return 'info';
  }
  return value as LogLevel;
}

function validateLogFormat(value: string): LogFormat {
  return value === 'pretty' ? 'pretty' : 'json';
}

function validatePrivacyMode(value: string): PrivacyMode {
  const validModes: PrivacyMode[] = ['standard', 'enhanced', 'maximum'];
  if (!validModes.includes(value as PrivacyMode)) {
    return 'standard';
  }
  return value as PrivacyMode;
}

function validateLocationObfuscation(value: string): LocationObfuscation {
  const validModes: LocationObfuscation[] = ['none', 'fuzzy', 'region', 'hidden'];
  if (!validModes.includes(value as LocationObfuscation)) {
    return 'fuzzy';
  }
  return value as LocationObfuscation;
}

function validateStorageProvider(value: string): StorageProvider {
  const validProviders: StorageProvider[] = ['local', 's3', 'r2', 'minio'];
  if (!validProviders.includes(value as StorageProvider)) {
    return 'local';
  }
  return value as StorageProvider;
}

function validateNodeEnv(value: string): 'development' | 'production' | 'test' {
  if (value === 'production' || value === 'test') {
    return value;
  }
  return 'development';
}

/**
 * Load and validate environment configuration
 */
function loadEnv(): EnvConfig {
  const nodeEnv = validateNodeEnv(process.env.NODE_ENV || 'development');

  return {
    // Application
    nodeEnv,
    port: getEnvNumber('PORT', 3001),
    apiUrl: getEnvString('NEXT_PUBLIC_API_URL', 'http://localhost:3001'),
    appName: getEnvString('NEXT_PUBLIC_APP_NAME', 'LocalGreenChain'),

    // Database
    databaseUrl: getEnvString('DATABASE_URL', 'postgresql://lgc:lgc_password@localhost:5432/localgreenchain'),
    dbHost: getEnvString('DB_HOST', 'localhost'),
    dbPort: getEnvNumber('DB_PORT', 5432),
    dbUser: getEnvString('DB_USER', 'lgc'),
    dbPassword: getEnvString('DB_PASSWORD', 'lgc_password'),
    dbName: getEnvString('DB_NAME', 'localgreenchain'),

    // Redis
    redisUrl: getEnvString('REDIS_URL', 'redis://localhost:6379'),
    redisHost: getEnvString('REDIS_HOST', 'localhost'),
    redisPort: getEnvNumber('REDIS_PORT', 6379),

    // Authentication
    nextAuthUrl: getEnvString('NEXTAUTH_URL', 'http://localhost:3001'),
    nextAuthSecret: getEnvString('NEXTAUTH_SECRET', 'development-secret-change-in-production'),
    githubClientId: process.env.GITHUB_CLIENT_ID,
    githubClientSecret: process.env.GITHUB_CLIENT_SECRET,
    googleClientId: process.env.GOOGLE_CLIENT_ID,
    googleClientSecret: process.env.GOOGLE_CLIENT_SECRET,

    // Sentry
    sentryDsn: process.env.SENTRY_DSN || process.env.NEXT_PUBLIC_SENTRY_DSN,
    sentryOrg: process.env.SENTRY_ORG,
    sentryProject: process.env.SENTRY_PROJECT,
    sentryAuthToken: process.env.SENTRY_AUTH_TOKEN,

    // Logging
    logLevel: validateLogLevel(getEnvString('LOG_LEVEL', 'info')),
    logFormat: validateLogFormat(getEnvString('LOG_FORMAT', 'json')),

    // Monitoring
    prometheusEnabled: getEnvBoolean('PROMETHEUS_ENABLED', false),
    metricsPort: getEnvNumber('METRICS_PORT', 9091),

    // Plants.net
    plantsNetApiKey: process.env.PLANTS_NET_API_KEY,

    // Tor
    torEnabled: getEnvBoolean('TOR_ENABLED', false),
    torSocksHost: getEnvString('TOR_SOCKS_HOST', '127.0.0.1'),
    torSocksPort: getEnvNumber('TOR_SOCKS_PORT', 9050),
    torControlPort: getEnvNumber('TOR_CONTROL_PORT', 9051),
    torHiddenServiceDir: getEnvString('TOR_HIDDEN_SERVICE_DIR', '/var/lib/tor/localgreenchain'),

    // Privacy
    defaultPrivacyMode: validatePrivacyMode(getEnvString('DEFAULT_PRIVACY_MODE', 'standard')),
    allowAnonymousRegistration: getEnvBoolean('ALLOW_ANONYMOUS_REGISTRATION', true),
    locationObfuscationDefault: validateLocationObfuscation(getEnvString('LOCATION_OBFUSCATION_DEFAULT', 'fuzzy')),

    // Storage
    storageProvider: validateStorageProvider(getEnvString('STORAGE_PROVIDER', 'local')),
    s3Bucket: process.env.S3_BUCKET,
    s3Region: process.env.S3_REGION,
    s3AccessKeyId: process.env.S3_ACCESS_KEY_ID,
    s3SecretAccessKey: process.env.S3_SECRET_ACCESS_KEY,
    s3Endpoint: process.env.S3_ENDPOINT,

    // Email
    smtpHost: getEnvString('SMTP_HOST', 'localhost'),
    smtpPort: getEnvNumber('SMTP_PORT', 1025),
    smtpUser: process.env.SMTP_USER,
    smtpPassword: process.env.SMTP_PASSWORD,
    smtpFrom: getEnvString('SMTP_FROM', 'noreply@localgreenchain.local'),

    // Rate Limiting
    rateLimitWindowMs: getEnvNumber('RATE_LIMIT_WINDOW_MS', 60000),
    rateLimitMaxRequests: getEnvNumber('RATE_LIMIT_MAX_REQUESTS', 100),

    // Security
    corsOrigins: getEnvArray('CORS_ORIGINS', ['http://localhost:3001']),
    cspReportUri: process.env.CSP_REPORT_URI,

    // Feature Flags
    isProduction: nodeEnv === 'production',
    isDevelopment: nodeEnv === 'development',
    isTest: nodeEnv === 'test',
  };
}

// Export singleton config
export const env = loadEnv();

// Re-export types
export type { EnvConfig, LogLevel, LogFormat, PrivacyMode, LocationObfuscation, StorageProvider };
