// Environment Variable Validation
// Validates all required environment variables at application startup

import { logger } from '@/infrastructure/monitoring/logger';

interface EnvVarConfig {
  required: boolean;
  description: string;
  validator?: (value: string) => boolean;
  errorMessage?: string;
}

interface EnvConfig {
  [key: string]: EnvVarConfig;
}

// Environment variable definitions
const envConfig: EnvConfig = {
  // Database
  DATABASE_URL: {
    required: true,
    description: 'PostgreSQL database connection string',
    validator: (value) => value.startsWith('postgresql://') || value.startsWith('postgres://'),
    errorMessage: 'DATABASE_URL must be a valid PostgreSQL connection string',
  },

  // Security
  JWT_SECRET: {
    required: true,
    description: 'JWT secret key for token signing',
    validator: (value) => value.length >= 32,
    errorMessage: 'JWT_SECRET must be at least 32 characters long',
  },

  // API Configuration
  PORT: {
    required: false,
    description: 'Server port (default: 3000)',
    validator: (value) => {
      const port = parseInt(value, 10);
      return !isNaN(port) && port > 0 && port < 65536;
    },
    errorMessage: 'PORT must be a valid port number (1-65535)',
  },

  ALLOWED_ORIGINS: {
    required: process.env.NODE_ENV === 'production',
    description: 'Comma-separated list of allowed CORS origins',
    validator: (value) => {
      if (process.env.NODE_ENV === 'production' && value === '*') {
        return false;
      }
      return value.split(',').every((origin) => {
        try {
          new URL(origin.trim());
          return true;
        } catch {
          return false;
        }
      });
    },
    errorMessage:
      'ALLOWED_ORIGINS must be comma-separated valid URLs. Wildcard (*) not allowed in production.',
  },

  // HSM Configuration
  HSM_ENABLED: {
    required: false,
    description: 'Enable HSM integration (default: false)',
    validator: (value) => value === 'true' || value === 'false',
    errorMessage: 'HSM_ENABLED must be "true" or "false"',
  },

  // Logging
  LOG_LEVEL: {
    required: false,
    description: 'Logging level (default: info)',
    validator: (value) => ['error', 'warn', 'info', 'debug'].includes(value),
    errorMessage: 'LOG_LEVEL must be one of: error, warn, info, debug',
  },

  // Node Environment
  NODE_ENV: {
    required: false,
    description: 'Node environment (development, staging, production)',
    validator: (value) => ['development', 'staging', 'production', 'test'].includes(value),
    errorMessage: 'NODE_ENV must be one of: development, staging, production, test',
  },

  // IRU - Proxmox VE Configuration
  PROXMOX_HOST: {
    required: process.env.NODE_ENV === 'production',
    description: 'Proxmox VE host address',
    validator: (value) => {
      try {
        new URL(value.startsWith('http') ? value : `https://${value}`);
        return true;
      } catch {
        return /^[a-zA-Z0-9.-]+$/.test(value); // Hostname or IP
      }
    },
    errorMessage: 'PROXMOX_HOST must be a valid hostname or IP address',
  },
  PROXMOX_USERNAME: {
    required: process.env.NODE_ENV === 'production',
    description: 'Proxmox VE username',
    validator: (value) => value.length > 0,
    errorMessage: 'PROXMOX_USERNAME cannot be empty',
  },
  PROXMOX_PASSWORD: {
    required: process.env.NODE_ENV === 'production',
    description: 'Proxmox VE password',
    validator: (value) => value.length >= 8,
    errorMessage: 'PROXMOX_PASSWORD must be at least 8 characters long',
  },

  // IRU - Payment Processing
  STRIPE_SECRET_KEY: {
    required: false,
    description: 'Stripe secret key for payment processing',
    validator: (value) => value.startsWith('sk_'),
    errorMessage: 'STRIPE_SECRET_KEY must start with "sk_"',
  },
  STRIPE_WEBHOOK_SECRET: {
    required: false,
    description: 'Stripe webhook secret for signature verification',
    validator: (value) => value.startsWith('whsec_') || value.length >= 32,
    errorMessage: 'STRIPE_WEBHOOK_SECRET must be a valid webhook secret',
  },
  BRAINTREE_MERCHANT_ID: {
    required: false,
    description: 'Braintree merchant ID',
    validator: (value) => value.length > 0,
    errorMessage: 'BRAINTREE_MERCHANT_ID cannot be empty',
  },
  BRAINTREE_WEBHOOK_SECRET: {
    required: false,
    description: 'Braintree webhook secret for signature verification',
    validator: (value) => value.length >= 32,
    errorMessage: 'BRAINTREE_WEBHOOK_SECRET must be at least 32 characters long',
  },

  // IRU - E-Signature
  DOCUSIGN_ACCOUNT_ID: {
    required: false,
    description: 'DocuSign account ID',
    validator: (value) => /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value),
    errorMessage: 'DOCUSIGN_ACCOUNT_ID must be a valid UUID',
  },
  DOCUSIGN_ACCESS_TOKEN: {
    required: false,
    description: 'DocuSign access token',
    validator: (value) => value.length >= 32,
    errorMessage: 'DOCUSIGN_ACCESS_TOKEN must be at least 32 characters long',
  },

  // IRU - Notifications
  EMAIL_PROVIDER: {
    required: false,
    description: 'Email provider (sendgrid, ses, smtp)',
    validator: (value) => ['sendgrid', 'ses', 'smtp'].includes(value),
    errorMessage: 'EMAIL_PROVIDER must be one of: sendgrid, ses, smtp',
  },
  EMAIL_API_KEY: {
    required: false,
    description: 'Email provider API key',
    validator: (value) => value.length >= 16,
    errorMessage: 'EMAIL_API_KEY must be at least 16 characters long',
  },
  SMS_PROVIDER: {
    required: false,
    description: 'SMS provider (twilio)',
    validator: (value) => ['twilio'].includes(value),
    errorMessage: 'SMS_PROVIDER must be twilio',
  },
  TWILIO_ACCOUNT_SID: {
    required: false,
    description: 'Twilio account SID',
    validator: (value) => value.startsWith('AC') && value.length === 34,
    errorMessage: 'TWILIO_ACCOUNT_SID must be a valid Twilio account SID',
  },
  TWILIO_AUTH_TOKEN: {
    required: false,
    description: 'Twilio auth token',
    validator: (value) => value.length >= 32,
    errorMessage: 'TWILIO_AUTH_TOKEN must be at least 32 characters long',
  },

  // Crypto.com OTC API
  CRYPTO_COM_API_KEY: {
    required: false,
    description: 'Crypto.com OTC API key for institutional trading',
    validator: (value) => value.length >= 16,
    errorMessage: 'CRYPTO_COM_API_KEY must be at least 16 characters',
  },
  CRYPTO_COM_API_SECRET: {
    required: false,
    description: 'Crypto.com OTC API secret',
    validator: (value) => value.length >= 16,
    errorMessage: 'CRYPTO_COM_API_SECRET must be at least 16 characters',
  },
  CRYPTO_COM_ENVIRONMENT: {
    required: false,
    description: 'Crypto.com environment (production, uat)',
    validator: (value) => ['production', 'uat'].includes(value),
    errorMessage: 'CRYPTO_COM_ENVIRONMENT must be production or uat',
  },

  // IRU - Monitoring
  PROMETHEUS_PUSH_GATEWAY: {
    required: false,
    description: 'Prometheus push gateway URL',
    validator: (value) => {
      try {
        new URL(value);
        return true;
      } catch {
        return false;
      }
    },
    errorMessage: 'PROMETHEUS_PUSH_GATEWAY must be a valid URL',
  },
};

/**
 * Validate environment variables
 * @throws Error if validation fails
 */
export function validateEnvironment(): void {
  const errors: string[] = [];
  const warnings: string[] = [];

  for (const [key, config] of Object.entries(envConfig)) {
    const value = process.env[key];

    // Check if required
    if (config.required && !value) {
      errors.push(
        `Missing required environment variable: ${key}\n  Description: ${config.description}`
      );
      continue;
    }

    // Skip validation if not set and not required
    if (!value) {
      continue;
    }

    // Run validator if provided
    if (config.validator && !config.validator(value)) {
      const errorMsg = config.errorMessage || `Invalid value for ${key}`;
      if (config.required) {
        errors.push(`Invalid environment variable ${key}: ${errorMsg}\n  Value: ${value}`);
      } else {
        warnings.push(`Invalid environment variable ${key}: ${errorMsg}\n  Value: ${value}`);
      }
    }
  }

  // Log warnings
  if (warnings.length > 0) {
    warnings.forEach((warning) => logger.warn(warning));
  }

  // Throw if there are errors
  if (errors.length > 0) {
    const errorMessage = `Environment validation failed:\n${errors.join('\n\n')}`;
    logger.error(errorMessage);
    throw new Error(errorMessage);
  }

  logger.info('Environment variables validated successfully');
}

/**
 * Get validated environment variable
 */
export function getEnv(key: string, defaultValue?: string): string {
  const value = process.env[key];
  if (!value && defaultValue === undefined) {
    throw new Error(`Environment variable ${key} is not set and no default provided`);
  }
  return value || defaultValue || '';
}

