import * as Joi from 'joi';

export const validationSchema = Joi.object({
  NODE_ENV: Joi.string().valid('development', 'test', 'production').default('development'),
  PORT: Joi.number().default(4000),
  HOST: Joi.string().default('0.0.0.0'),
  PUBLIC_BASE_URL: Joi.string().uri().optional(),
  PUBLIC_WEB_URL: Joi.string().uri().optional(),
  SHARE_BASE_URL: Joi.string().uri().optional(),
  RESPONSE_ENVELOPE_ENABLED: Joi.boolean().truthy('true').falsy('false').default(false),
  GLOBAL_PREFIX: Joi.string().default('api/v1'),
  CORS_ORIGINS: Joi.string().allow('').optional(),
  MONGODB_URI: Joi.string().required(),
  MONGODB_AUTO_INDEX: Joi.boolean().truthy('true').falsy('false').optional(),
  MONGODB_MIN_POOL_SIZE: Joi.number().integer().min(0).max(500).default(5),
  MONGODB_MAX_POOL_SIZE: Joi.number().integer().min(1).max(1000).default(100),
  MONGODB_MAX_IDLE_TIME_MS: Joi.number().integer().min(1000).max(600000).default(60000),
  MONGODB_SERVER_SELECTION_TIMEOUT_MS: Joi.number().integer().min(1000).max(120000).default(10000),
  MONGODB_SOCKET_TIMEOUT_MS: Joi.number().integer().min(1000).max(600000).default(45000),
  SEARCH_ENGINE: Joi.string().valid('auto', 'atlas', 'regex').default('auto'),
  SEARCH_ATLAS_USER_INDEX: Joi.string().default('users_search'),
  SEARCH_ATLAS_POST_INDEX: Joi.string().default('posts_search'),
  SEARCH_FALLBACK_ENABLED: Joi.boolean().truthy('true').falsy('false').default(true),
  SEARCH_ATLAS_RETRY_SECONDS: Joi.number().integer().min(30).max(3600).default(300),
  JWT_ACCESS_SECRET: Joi.string().min(16).required(),
  JWT_ACCESS_EXPIRES_IN: Joi.string().default('15m'),
  JWT_REFRESH_SECRET: Joi.string().min(16).required(),
  JWT_REFRESH_EXPIRES_IN: Joi.string().default('30d'),
  SUPERADMIN_EMAIL: Joi.string().email().required(),
  SUPERADMIN_PASSWORD: Joi.string().min(8).allow('').optional(),
  SUPERADMIN_PASSWORD_HASH: Joi.when('NODE_ENV', {
    is: 'production',
    then: Joi.string().pattern(/^\$2[aby]\$\d{2}\$.{53}$/).required(),
    otherwise: Joi.string().allow('').optional(),
  }),
  SUPERADMIN_ACCESS_SECRET: Joi.string().min(16).required(),
  SUPERADMIN_ACCESS_EXPIRES_IN: Joi.string().default('15m'),
  SUPERADMIN_REFRESH_SECRET: Joi.string().min(16).required(),
  SUPERADMIN_REFRESH_EXPIRES_IN: Joi.string().default('30d'),
  SUPERADMIN_TOTP_SECRET: Joi.string().pattern(/^[A-Z2-7\s=-]{16,}$/i).allow('').optional(),
  GOOGLE_CLIENT_ID: Joi.string().allow('').optional(),
  GOOGLE_CLIENT_SECRET: Joi.string().allow('').optional(),
  GOOGLE_CALLBACK_URL: Joi.string().uri().optional(),
  EMAIL_ENABLED: Joi.boolean().truthy('true').falsy('false').default(false),
  EMAIL_SMTP_HOST: Joi.string().allow('').optional(),
  EMAIL_SMTP_PORT: Joi.number().default(587),
  EMAIL_SMTP_SECURE: Joi.boolean().truthy('true').falsy('false').default(false),
  EMAIL_SMTP_USER: Joi.string().allow('').optional(),
  EMAIL_SMTP_PASS: Joi.string().allow('').optional(),
  EMAIL_FROM_NAME: Joi.string().default('Oudelaa'),
  EMAIL_FROM_EMAIL: Joi.string().allow('').optional(),
  AI_MUSIC_ENABLED: Joi.boolean().truthy('true').falsy('false').default(false),
  AI_MUSIC_API_KEY: Joi.string().allow('').optional(),
  GOOGLE_APPLICATION_CREDENTIALS_JSON_BASE64: Joi.string().allow('').optional(),
  AI_MUSIC_PROJECT_ID: Joi.string().allow('').optional(),
  AI_MUSIC_LOCATION: Joi.string().default('us-central1'),
  AI_MUSIC_MODEL: Joi.string().default('lyria-002'),
  BCRYPT_SALT_ROUNDS: Joi.number().min(8).max(15).default(12),
  REFRESH_TOKEN_HASH_SECRET: Joi.string().allow('').optional(),
  HTTP_BODY_LIMIT: Joi.string().pattern(/^\d+(kb|mb)$/i).default('1mb'),
  HTTP_REQUEST_TIMEOUT_MS: Joi.number().integer().min(1000).max(300000).default(30000),
  HTTP_SERVER_REQUEST_TIMEOUT_MS: Joi.number()
    .integer()
    .min(1000)
    .max(900000)
    .default(120000),
  HTTP_HEADERS_TIMEOUT_MS: Joi.number().integer().min(1000).max(120000).default(15000),
  HTTP_KEEP_ALIVE_TIMEOUT_MS: Joi.number().integer().min(1000).max(60000).default(5000),
  HTTP_MAX_REQUESTS_PER_SOCKET: Joi.number().integer().min(1).max(100000).default(1000),
  SHUTDOWN_GRACE_PERIOD_MS: Joi.number().integer().min(1000).max(120000).default(30000),
  METRICS_EVENT_LOOP_RESOLUTION_MS: Joi.number().integer().min(10).max(1000).default(20),
  METRICS_EVENT_LOOP_LAG_WARN_MS: Joi.number().integer().min(10).max(10000).default(100),
  METRICS_MAX_ROUTES: Joi.number().integer().min(10).max(10000).default(500),
  REDIS_ENABLED: Joi.boolean().truthy('true').falsy('false').default(false),
  REDIS_URL: Joi.string().allow('').optional(),
  REDIS_HOST: Joi.string().default('127.0.0.1'),
  REDIS_PORT: Joi.number().default(6379),
  REDIS_USERNAME: Joi.string().allow('').optional(),
  REDIS_PASSWORD: Joi.string().allow('').optional(),
  REDIS_DB: Joi.number().min(0).default(0),
  REDIS_KEY_PREFIX: Joi.string().default('oudelaa'),
  REDIS_SOCKET_ADAPTER_ENABLED: Joi.boolean().truthy('true').falsy('false').default(false),
  QUEUE_ENABLED: Joi.boolean().truthy('true').falsy('false').default(false),
  QUEUE_NAME: Joi.string().default('app-jobs'),
  QUEUE_DEFAULT_ATTEMPTS: Joi.number().min(1).max(20).default(3),
  QUEUE_DEFAULT_BACKOFF_MS: Joi.number().min(100).max(600000).default(1000),
  QUEUE_REMOVE_ON_COMPLETE: Joi.boolean().truthy('true').falsy('false').default(true),
  QUEUE_WORKER_CONCURRENCY: Joi.number().min(1).max(100).default(5),
  NOTIFICATION_SERVICE_ENABLED: Joi.boolean().truthy('true').falsy('false').default(false),
  OUTBOX_DISPATCHER_ENABLED: Joi.boolean().truthy('true').falsy('false').default(false),
  OUTBOX_POLL_INTERVAL_MS: Joi.number().integer().min(100).max(60000).default(1000),
  OUTBOX_BATCH_SIZE: Joi.number().integer().min(1).max(500).default(25),
  OUTBOX_MAX_ATTEMPTS: Joi.number().integer().min(1).max(100).default(8),
  OUTBOX_LEASE_TIMEOUT_MS: Joi.number().integer().min(1000).max(3600000).default(60000),
  OUTBOX_RETRY_BASE_MS: Joi.number().integer().min(100).max(600000).default(1000),
  OUTBOX_RETRY_MAX_MS: Joi.number().integer().min(100).max(3600000).default(60000),
  RABBITMQ_URL: Joi.string().uri().allow('').optional(),
  RABBITMQ_HOST: Joi.string().default('127.0.0.1'),
  RABBITMQ_PORT: Joi.number().integer().min(1).max(65535).default(5672),
  RABBITMQ_USERNAME: Joi.string().allow('').optional(),
  RABBITMQ_PASSWORD: Joi.string().allow('').optional(),
  RABBITMQ_VHOST: Joi.string().default('/'),
  RABBITMQ_TLS_ENABLED: Joi.boolean().truthy('true').falsy('false').default(false),
  RABBITMQ_TLS_REQUIRED: Joi.boolean().truthy('true').falsy('false').default(true),
  RABBITMQ_CA_CERT_BASE64: Joi.string().allow('').optional(),
  RABBITMQ_CA_CERT_PATH: Joi.string().allow('').optional(),
  RABBITMQ_CLIENT_CERT_BASE64: Joi.string().allow('').optional(),
  RABBITMQ_CLIENT_CERT_PATH: Joi.string().allow('').optional(),
  RABBITMQ_CLIENT_KEY_BASE64: Joi.string().allow('').optional(),
  RABBITMQ_CLIENT_KEY_PATH: Joi.string().allow('').optional(),
  RABBITMQ_TLS_REJECT_UNAUTHORIZED: Joi.boolean().truthy('true').falsy('false').default(true),
  RABBITMQ_SERVERNAME: Joi.string().allow('').optional(),
  RABBITMQ_HEARTBEAT_SECONDS: Joi.number().integer().min(1).max(120).default(10),
  RABBITMQ_RECONNECT_SECONDS: Joi.number().integer().min(1).max(300).default(5),
  RABBITMQ_CONNECTION_TIMEOUT_MS: Joi.number().integer().min(100).max(120000).default(10000),
  NOTIFICATION_RPC_TIMEOUT_MS: Joi.number().integer().min(100).max(30000).default(3000),
  NOTIFICATION_RPC_RETRIES: Joi.number().integer().min(0).max(5).default(1),
  NOTIFICATION_CIRCUIT_FAILURE_THRESHOLD: Joi.number().integer().min(1).max(20).default(3),
  NOTIFICATION_CIRCUIT_RESET_MS: Joi.number().integer().min(1000).max(300000).default(15000),
  STORAGE_PROVIDER: Joi.string().valid('local', 's3').default('local'),
  MEDIA_ACCESS_MODE: Joi.string().valid('direct', 'signed').default('direct'),
  SIGNED_URL_EXPIRES_SECONDS: Joi.number().integer().min(1).max(604800).default(86400),
  STORAGE_BASE_PATH: Joi.string().default('uploads'),
  STORAGE_PUBLIC_BASE_URL: Joi.string().allow('').optional(),
  S3_BUCKET: Joi.string().allow('').optional(),
  S3_REGION: Joi.string().allow('').default('auto'),
  S3_ENDPOINT: Joi.string().allow('').optional(),
  S3_ACCESS_KEY_ID: Joi.string().allow('').optional(),
  S3_SECRET_ACCESS_KEY: Joi.string().allow('').optional(),
  S3_PUBLIC_BASE_URL: Joi.string().allow('').optional(),
  S3_FORCE_PATH_STYLE: Joi.boolean().truthy('true').falsy('false').default(false),
  S3_HEALTH_WRITE_TEST_ENABLED: Joi.boolean().truthy('true').falsy('false').default(false),
  IMAGE_PROCESSING_ENABLED: Joi.boolean().truthy('true').falsy('false').optional(),
  IMAGE_PROCESSING_FFMPEG_PATH: Joi.string().allow('').optional(),
  IMAGE_PROCESSING_LOW_WIDTH: Joi.number().min(160).max(1920).default(360),
  IMAGE_PROCESSING_MEDIUM_WIDTH: Joi.number().min(160).max(2560).default(720),
  IMAGE_PROCESSING_HIGH_WIDTH: Joi.number().min(320).max(3840).default(1280),
  IMAGE_PROCESSING_QUALITY: Joi.number().min(40).max(100).default(78),
  VIDEO_PROCESSING_ENABLED: Joi.boolean().truthy('true').falsy('false').default(false),
  VIDEO_PROCESSING_FFMPEG_PATH: Joi.string().default('ffmpeg'),
  VIDEO_PROCESSING_FFPROBE_PATH: Joi.string().allow('').optional(),
  VIDEO_PROCESSING_MAX_WIDTH: Joi.number().min(320).max(3840).default(1280),
  VIDEO_PROCESSING_MAX_FPS: Joi.number().min(12).max(60).default(30),
  VIDEO_PROCESSING_CRF: Joi.number().min(18).max(35).default(28),
  VIDEO_PROCESSING_PRESET: Joi.string()
    .valid('ultrafast', 'superfast', 'veryfast', 'faster', 'fast', 'medium', 'slow')
    .default('veryfast'),
  VIDEO_PROCESSING_AUDIO_BITRATE_KBPS: Joi.number().min(64).max(320).default(128),
  VIDEO_PROCESSING_GENERATE_THUMBNAILS: Joi.boolean().truthy('true').falsy('false').default(true),
  VIDEO_PROCESSING_GENERATE_HLS: Joi.boolean().truthy('true').falsy('false').default(true),
  VIDEO_PROCESSING_HLS_SEGMENT_DURATION_SECONDS: Joi.number().min(2).max(20).default(4),
  VIDEO_PROCESSING_THUMBNAIL_WIDTH: Joi.number().min(160).max(1920).default(720),
  AUDIO_PROCESSING_ENABLED: Joi.boolean().truthy('true').falsy('false').default(false),
  AUDIO_WAVEFORM_PEAKS: Joi.number().min(16).max(256).default(100),
  LOG_LEVEL: Joi.string().valid('error', 'warn', 'log', 'debug', 'verbose').default('log'),
  REQUEST_LOGGING_ENABLED: Joi.boolean().truthy('true').falsy('false').default(true),
  FEED_CACHE_ENABLED: Joi.boolean().truthy('true').falsy('false').default(true),
  FEED_CACHE_USER_TTL_SECONDS: Joi.number().min(1).max(3600).default(15),
  FEED_CACHE_TRENDING_TTL_SECONDS: Joi.number().min(1).max(3600).default(30),
  FEED_CACHE_RANKING_PROFILE_TTL_SECONDS: Joi.number().min(1).max(3600).default(30),
  FEED_TIMING_LOGS_ENABLED: Joi.boolean().truthy('true').falsy('false').default(false),
  HTTP_COMPRESSION_ENABLED: Joi.boolean().truthy('true').falsy('false').default(true),
  HTTP_COMPRESSION_THRESHOLD_BYTES: Joi.number().integer().min(0).max(1048576).default(1024),
  MODERATION_BLOCKED_TERMS: Joi.string().allow('').optional(),
  PASSWORD_RESET_CODE_EXPIRES_MINUTES: Joi.number().min(1).max(60).default(10),
  PASSWORD_RESET_MAX_ATTEMPTS: Joi.number().min(1).max(10).default(5),
  PASSWORD_RESET_TOKEN_SECRET: Joi.string().allow('').optional(),
  PASSWORD_RESET_TOKEN_EXPIRES_IN: Joi.string().default('15m'),
  EMAIL_VERIFICATION_CODE_EXPIRES_MINUTES: Joi.number().min(1).max(60).default(10),
  EMAIL_VERIFICATION_MAX_ATTEMPTS: Joi.number().min(1).max(10).default(5),
  SWAGGER_TITLE: Joi.string().default('Oudelaa API'),
  SWAGGER_ENABLED: Joi.boolean().truthy('true').falsy('false').optional(),
  SWAGGER_DESCRIPTION: Joi.string().default('Social media backend API documentation'),
  SWAGGER_VERSION: Joi.string().default('1.0.0'),
  SWAGGER_PATH: Joi.string().default('docs'),
}).custom((value: Record<string, unknown>, helpers: Joi.CustomHelpers) => {
  if (value.STORAGE_PROVIDER === 'local' && value.MEDIA_ACCESS_MODE === 'signed') {
    return helpers.message({ custom: 'MEDIA_ACCESS_MODE=signed requires STORAGE_PROVIDER=s3' });
  }
  if (Number(value.HTTP_HEADERS_TIMEOUT_MS) <= Number(value.HTTP_KEEP_ALIVE_TIMEOUT_MS)) {
    return helpers.message({
      custom: 'HTTP_HEADERS_TIMEOUT_MS must be greater than HTTP_KEEP_ALIVE_TIMEOUT_MS',
    });
  }
  if (Number(value.HTTP_SERVER_REQUEST_TIMEOUT_MS) < Number(value.HTTP_HEADERS_TIMEOUT_MS)) {
    return helpers.message({
      custom: 'HTTP_SERVER_REQUEST_TIMEOUT_MS must be at least HTTP_HEADERS_TIMEOUT_MS',
    });
  }
  if (Number(value.OUTBOX_RETRY_MAX_MS) < Number(value.OUTBOX_RETRY_BASE_MS)) {
    return helpers.message({ custom: 'OUTBOX_RETRY_MAX_MS must be at least OUTBOX_RETRY_BASE_MS' });
  }
  if (value.NOTIFICATION_SERVICE_ENABLED !== value.OUTBOX_DISPATCHER_ENABLED) {
    return helpers.message({
      custom: 'Phase-1 Gateway activation requires NOTIFICATION_SERVICE_ENABLED and OUTBOX_DISPATCHER_ENABLED to have the same value',
    });
  }
  if (value.NODE_ENV === 'production' && value.NOTIFICATION_SERVICE_ENABLED === true) {
    const rawUrl = String(value.RABBITMQ_URL ?? '');
    let url: URL | undefined;
    try { if (rawUrl) url = new URL(rawUrl); } catch { return helpers.message({ custom: 'RABBITMQ_URL is invalid' }); }
    const username = url?.username ? decodeURIComponent(url.username) : String(value.RABBITMQ_USERNAME ?? '');
    const password = url?.password ? decodeURIComponent(url.password) : String(value.RABBITMQ_PASSWORD ?? '');
    if (!username || !password || username === 'guest' || password === 'guest') {
      return helpers.message({ custom: 'Production notification routing requires non-guest RabbitMQ credentials' });
    }
    if (value.RABBITMQ_TLS_REQUIRED === true && url?.protocol !== 'amqps:' && value.RABBITMQ_TLS_ENABLED !== true) {
      return helpers.message({ custom: 'Production notification routing requires RabbitMQ TLS/amqps' });
    }
  }
  return value;
}, 'cross-field configuration validation');
