/**
 * Zulip配置模块
 *
 * 功能描述：
 * - 定义Zulip集成系统的配置接口
 * - 提供配置验证功能
 * - 支持环境变量和配置文件两种配置方式
 * - 实现配置热重载
 *
 * 职责分离：
 * - 配置定义层：定义各类配置接口和默认值
 * - 配置加载层：从环境变量和文件加载配置
 * - 配置验证层：验证配置的完整性和有效性
 *
 * 配置来源优先级：
 * 1. 环境变量（最高优先级）
 * 2. 配置文件
 * 3. 默认值（最低优先级）
 *
 * 依赖模块：
 * - @nestjs/config: NestJS配置模块
 *
 * 最近修改：
 * - 2026-01-12: 代码规范优化 - 修正注释规范和修改记录格式 (修改者: moyin)
 * - 2026-01-08: 文件夹扁平化 - 从config/子文件夹移动到上级目录 (修改者: moyin)
 * - 2026-01-07: 代码规范优化 - 更新import路径和注释规范 (修改者: moyin)
 *
 * @author moyin
 * @version 1.0.3
 * @since 2025-12-25
 * @lastModified 2026-01-12
 */

import { registerAs } from '@nestjs/config';

/**
 * Zulip服务器配置接口
 */
export interface ZulipServerConfig {
  /** Zulip服务器URL */
  serverUrl: string;
  /** Zulip机器人邮箱 */
  botEmail: string;
  /** Zulip机器人API Key */
  botApiKey: string;
}

/**
 * WebSocket配置接口
 */
export interface WebSocketConfig {
  /** WebSocket端口 */
  port: number;
  /** WebSocket命名空间 */
  namespace: string;
  /** 心跳间隔（毫秒） */
  pingInterval: number;
  /** 心跳超时（毫秒） */
  pingTimeout: number;
}

/**
 * 消息配置接口
 */
export interface MessageConfig {
  /** 消息频率限制（条/分钟） */
  rateLimit: number;
  /** 消息最大长度 */
  maxLength: number;
  /** 是否启用内容过滤 */
  contentFilterEnabled: boolean;
  /** 敏感词列表文件路径 */
  sensitiveWordsPath?: string;
}

/**
 * 会话配置接口
 */
export interface SessionConfig {
  /** 会话超时时间（分钟） */
  timeout: number;
  /** 清理间隔（分钟） */
  cleanupInterval: number;
  /** 最大连接数 */
  maxConnections: number;
}

/**
 * 错误处理配置接口
 */
export interface ErrorHandlingConfig {
  /** 是否启用降级模式 */
  degradedModeEnabled: boolean;
  /** 是否启用自动重连 */
  autoReconnectEnabled: boolean;
  /** 最大重连尝试次数 */
  maxReconnectAttempts: number;
  /** 重连基础延迟（毫秒） */
  reconnectBaseDelay: number;
  /** API超时时间（毫秒） */
  apiTimeout: number;
  /** 最大重试次数 */
  maxRetries: number;
}

/**
 * 监控配置接口
 */
export interface MonitoringConfig {
  /** 健康检查间隔（毫秒） */
  healthCheckInterval: number;
  /** 错误率阈值（0-1） */
  errorRateThreshold: number;
  /** API响应时间阈值（毫秒） */
  responseTimeThreshold: number;
  /** 内存使用阈值（0-1） */
  memoryThreshold: number;
}

/**
 * 安全配置接口
 */
export interface SecurityConfig {
  /** API Key加密密钥（生产环境必须配置） */
  apiKeyEncryptionKey?: string;
  /** 允许的Stream列表（空表示允许所有） */
  allowedStreams: string[];
}

/**
 * 完整的Zulip配置接口
 */
export interface ZulipConfiguration {
  /** Zulip服务器配置 */
  server: ZulipServerConfig;
  /** WebSocket配置 */
  websocket: WebSocketConfig;
  /** 消息配置 */
  message: MessageConfig;
  /** 会话配置 */
  session: SessionConfig;
  /** 错误处理配置 */
  errorHandling: ErrorHandlingConfig;
  /** 监控配置 */
  monitoring: MonitoringConfig;
  /** 安全配置 */
  security: SecurityConfig;
}

/**
 * 配置验证结果接口
 */
export interface ConfigValidationResult {
  /** 是否有效 */
  valid: boolean;
  /** 错误信息列表 */
  errors: string[];
  /** 警告信息列表 */
  warnings: string[];
}

/**
 * 默认配置值
 */
export const DEFAULT_ZULIP_CONFIG: ZulipConfiguration = {
  server: {
    serverUrl: 'https://your-zulip-server.com',
    botEmail: 'bot@example.com',
    botApiKey: '',
  },
  websocket: {
    port: 3000,
    namespace: '/game',
    pingInterval: 25000,
    pingTimeout: 5000,
  },
  message: {
    rateLimit: 10,
    maxLength: 10000,
    contentFilterEnabled: true,
  },
  session: {
    timeout: 30,
    cleanupInterval: 5,
    maxConnections: 1000,
  },
  errorHandling: {
    degradedModeEnabled: false,
    autoReconnectEnabled: true,
    maxReconnectAttempts: 5,
    reconnectBaseDelay: 5000,
    apiTimeout: 30000,
    maxRetries: 3,
  },
  monitoring: {
    healthCheckInterval: 60000,
    errorRateThreshold: 0.1,
    responseTimeThreshold: 5000,
    memoryThreshold: 0.9,
  },
  security: {
    allowedStreams: [],
  },
};


/**
 * 从环境变量加载Zulip配置
 *
 * 功能描述：
 * 从环境变量读取配置值，未设置的使用默认值
 *
 * @returns ZulipConfiguration 完整的Zulip配置对象
 */
export function loadZulipConfigFromEnv(): ZulipConfiguration {
  return {
    server: {
      serverUrl: process.env.ZULIP_SERVER_URL || DEFAULT_ZULIP_CONFIG.server.serverUrl,
      botEmail: process.env.ZULIP_BOT_EMAIL || DEFAULT_ZULIP_CONFIG.server.botEmail,
      botApiKey: process.env.ZULIP_BOT_API_KEY || DEFAULT_ZULIP_CONFIG.server.botApiKey,
    },
    websocket: {
      port: parseInt(process.env.WEBSOCKET_PORT || String(DEFAULT_ZULIP_CONFIG.websocket.port), 10),
      namespace: process.env.WEBSOCKET_NAMESPACE || DEFAULT_ZULIP_CONFIG.websocket.namespace,
      pingInterval: parseInt(process.env.WEBSOCKET_PING_INTERVAL || String(DEFAULT_ZULIP_CONFIG.websocket.pingInterval), 10),
      pingTimeout: parseInt(process.env.WEBSOCKET_PING_TIMEOUT || String(DEFAULT_ZULIP_CONFIG.websocket.pingTimeout), 10),
    },
    message: {
      rateLimit: parseInt(process.env.ZULIP_MESSAGE_RATE_LIMIT || String(DEFAULT_ZULIP_CONFIG.message.rateLimit), 10),
      maxLength: parseInt(process.env.ZULIP_MESSAGE_MAX_LENGTH || String(DEFAULT_ZULIP_CONFIG.message.maxLength), 10),
      contentFilterEnabled: process.env.ZULIP_CONTENT_FILTER_ENABLED !== 'false',
      sensitiveWordsPath: process.env.ZULIP_SENSITIVE_WORDS_PATH,
    },
    session: {
      timeout: parseInt(process.env.ZULIP_SESSION_TIMEOUT || String(DEFAULT_ZULIP_CONFIG.session.timeout), 10),
      cleanupInterval: parseInt(process.env.ZULIP_CLEANUP_INTERVAL || String(DEFAULT_ZULIP_CONFIG.session.cleanupInterval), 10),
      maxConnections: parseInt(process.env.ZULIP_MAX_CONNECTIONS || String(DEFAULT_ZULIP_CONFIG.session.maxConnections), 10),
    },
    errorHandling: {
      degradedModeEnabled: process.env.ZULIP_DEGRADED_MODE_ENABLED === 'true',
      autoReconnectEnabled: process.env.ZULIP_AUTO_RECONNECT_ENABLED !== 'false',
      maxReconnectAttempts: parseInt(process.env.ZULIP_MAX_RECONNECT_ATTEMPTS || String(DEFAULT_ZULIP_CONFIG.errorHandling.maxReconnectAttempts), 10),
      reconnectBaseDelay: parseInt(process.env.ZULIP_RECONNECT_BASE_DELAY || String(DEFAULT_ZULIP_CONFIG.errorHandling.reconnectBaseDelay), 10),
      apiTimeout: parseInt(process.env.ZULIP_API_TIMEOUT || String(DEFAULT_ZULIP_CONFIG.errorHandling.apiTimeout), 10),
      maxRetries: parseInt(process.env.ZULIP_MAX_RETRIES || String(DEFAULT_ZULIP_CONFIG.errorHandling.maxRetries), 10),
    },
    monitoring: {
      healthCheckInterval: parseInt(process.env.MONITORING_HEALTH_CHECK_INTERVAL || String(DEFAULT_ZULIP_CONFIG.monitoring.healthCheckInterval), 10),
      errorRateThreshold: parseFloat(process.env.MONITORING_ERROR_RATE_THRESHOLD || String(DEFAULT_ZULIP_CONFIG.monitoring.errorRateThreshold)),
      responseTimeThreshold: parseInt(process.env.MONITORING_RESPONSE_TIME_THRESHOLD || String(DEFAULT_ZULIP_CONFIG.monitoring.responseTimeThreshold), 10),
      memoryThreshold: parseFloat(process.env.MONITORING_MEMORY_THRESHOLD || String(DEFAULT_ZULIP_CONFIG.monitoring.memoryThreshold)),
    },
    security: {
      apiKeyEncryptionKey: process.env.ZULIP_API_KEY_ENCRYPTION_KEY,
      allowedStreams: (process.env.ZULIP_ALLOWED_STREAMS || '').split(',').filter(s => s.trim()),
    },
  };
}

/**
 * 验证Zulip配置
 *
 * 功能描述：
 * 验证配置的完整性和有效性，返回验证结果
 *
 * 验证规则：
 * 1. 必填字段不能为空
 * 2. 数值字段必须在有效范围内
 * 3. URL格式必须正确
 * 4. 生产环境必须配置API Key加密密钥
 *
 * @param config Zulip配置对象
 * @param isProduction 是否为生产环境
 * @returns ConfigValidationResult 验证结果
 */
export function validateZulipConfig(
  config: ZulipConfiguration,
  isProduction: boolean = false
): ConfigValidationResult {
  const errors: string[] = [];
  const warnings: string[] = [];

  // 验证服务器配置
  if (!config.server.serverUrl) {
    errors.push('缺少Zulip服务器URL (ZULIP_SERVER_URL)');
  } else if (!isValidUrl(config.server.serverUrl)) {
    errors.push('Zulip服务器URL格式无效');
  }

  if (!config.server.botEmail) {
    warnings.push('未配置Zulip机器人邮箱 (ZULIP_BOT_EMAIL)');
  } else if (!isValidEmail(config.server.botEmail)) {
    errors.push('Zulip机器人邮箱格式无效');
  }

  if (!config.server.botApiKey) {
    warnings.push('未配置Zulip机器人API Key (ZULIP_BOT_API_KEY)，将使用本地模式');
  }

  // 验证WebSocket配置
  if (config.websocket.port < 1 || config.websocket.port > 65535) {
    errors.push('WebSocket端口必须在1-65535范围内');
  }

  if (!config.websocket.namespace || !config.websocket.namespace.startsWith('/')) {
    errors.push('WebSocket命名空间必须以/开头');
  }

  // 验证消息配置
  if (config.message.rateLimit < 1) {
    errors.push('消息频率限制必须大于0');
  }

  if (config.message.maxLength < 1 || config.message.maxLength > 100000) {
    errors.push('消息最大长度必须在1-100000范围内');
  }

  // 验证会话配置
  if (config.session.timeout < 1) {
    errors.push('会话超时时间必须大于0');
  }

  if (config.session.cleanupInterval < 1) {
    errors.push('清理间隔必须大于0');
  }

  if (config.session.maxConnections < 1) {
    errors.push('最大连接数必须大于0');
  }

  // 验证错误处理配置
  if (config.errorHandling.maxReconnectAttempts < 0) {
    errors.push('最大重连尝试次数不能为负数');
  }

  if (config.errorHandling.apiTimeout < 1000) {
    warnings.push('API超时时间过短，建议至少1000毫秒');
  }

  // 验证监控配置
  if (config.monitoring.errorRateThreshold < 0 || config.monitoring.errorRateThreshold > 1) {
    errors.push('错误率阈值必须在0-1范围内');
  }

  if (config.monitoring.memoryThreshold < 0 || config.monitoring.memoryThreshold > 1) {
    errors.push('内存使用阈值必须在0-1范围内');
  }

  // 生产环境特殊验证
  if (isProduction) {
    if (!config.security.apiKeyEncryptionKey) {
      if (config.errorHandling.degradedModeEnabled) {
        warnings.push('降级模式未配置API Key加密密钥，Zulip API Key加密存取功能不可用');
      } else {
        errors.push('生产环境必须配置API Key加密密钥 (ZULIP_API_KEY_ENCRYPTION_KEY)');
      }
    } else if (config.security.apiKeyEncryptionKey.length < 32) {
      errors.push('API Key加密密钥长度必须至少32字符');
    }

    if (!config.server.botApiKey && !config.errorHandling.degradedModeEnabled) {
      errors.push('生产环境必须配置Zulip机器人API Key');
    }
  }

  return {
    valid: errors.length === 0,
    errors,
    warnings,
  };
}

/**
 * 验证URL格式
 *
 * @param url URL字符串
 * @returns boolean 是否有效
 */
function isValidUrl(url: string): boolean {
  try {
    new URL(url);
    return true;
  } catch {
    return false;
  }
}

/**
 * 验证邮箱格式
 *
 * @param email 邮箱字符串
 * @returns boolean 是否有效
 */
function isValidEmail(email: string): boolean {
  const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
  return emailRegex.test(email);
}

/**
 * NestJS配置工厂函数
 *
 * 功能描述：
 * 用于@nestjs/config模块的配置注册
 *
 * 使用方式：
 * ConfigModule.forRoot({
 *   load: [zulipConfig],
 * })
 */
export const zulipConfig = registerAs('zulip', () => {
  return loadZulipConfigFromEnv();
});
