/**
 * 配置管理服务
 *
 * 功能描述：
 * - 管理地图映射配置和系统配置
 * - 提供配置查询和热重载功能
 * - 验证配置有效性
 * - 支持配置文件的加载、验证和热重载
 * - 支持文件监听自动重载配置
 *
 * 主要方法：
 * - loadMapConfig(): 加载地图映射配置
 * - getStreamByMap(): 根据地图获取对应的Stream
 * - getTopicByObject(): 根据交互对象获取Topic
 * - reloadConfig(): 热重载配置
 * - validateConfig(): 验证配置有效性
 * - validateMapConfig(): 验证单个地图配置
 * - enableConfigWatcher(): 启用配置文件监听
 * - disableConfigWatcher(): 禁用配置文件监听
 *
 * 使用场景：
 * - 系统启动时加载配置
 * - 消息路由时查询映射关系
 * - 配置更新时热重载
 *
 * 依赖模块：
 * - AppLoggerService: 日志记录服务
 *
 * 最近修改：
 * - 2026-01-12: 代码规范优化 - 修正Core层注释措辞，将"业务逻辑"改为"处理流程" (修改者: moyin)
 * - 2026-01-12: 代码规范优化 - 修正注释规范和修改记录格式 (修改者: moyin)
 * - 2026-01-07: 代码规范优化 - 更新import路径和注释规范 (修改者: moyin)
 *
 * @author moyin
 * @version 1.0.3
 * @since 2025-12-25
 * @lastModified 2026-01-12
 */

import { Injectable, OnModuleDestroy, Logger } from '@nestjs/common';
import { Internal } from '../zulip.interfaces';
import {
  ZulipConfiguration,
  loadZulipConfigFromEnv,
  validateZulipConfig,
  DEFAULT_ZULIP_CONFIG,
} from '../zulip.config';
import * as fs from 'fs';
import * as path from 'path';

/**
 * 地图配置接口 - 从Internal命名空间重新导出
 */
export type MapConfig = Internal.MapConfig;

/**
 * 交互对象接口 - 从Internal命名空间重新导出
 */
export type InteractionObjectConfig = Internal.InteractionObject;

/**
 * 配置验证结果接口 - 从Internal命名空间重新导出
 */
export type ConfigValidationResult = Internal.ConfigValidationResult;

/**
 * 配置统计信息接口 - 从Internal命名空间重新导出
 */
export type ConfigStats = Internal.ConfigStats;

/**
 * Zulip配置接口（兼容旧版本）
 *
 * 功能描述：
 * - 定义Zulip集成系统的配置参数
 * - 支持环境变量和配置文件两种配置方式
 *
 * @since 2025-12-25
 * @deprecated 请使用ZulipConfiguration接口
 */
export interface ZulipConfig {
  // Zulip服务器配置
  zulipServerUrl: string;       // Zulip服务器URL
  zulipBotEmail: string;        // Zulip机器人邮箱
  zulipBotApiKey: string;       // Zulip机器人API Key

  // WebSocket配置
  websocketPort: number;        // WebSocket端口
  websocketNamespace: string;   // WebSocket命名空间

  // 消息配置
  messageRateLimit: number;     // 消息频率限制（条/分钟）
  messageMaxLength: number;     // 消息最大长度

  // 会话配置
  sessionTimeout: number;       // 会话超时时间（分钟）
  cleanupInterval: number;      // 清理间隔（分钟）

  // 安全配置
  enableContentFilter: boolean; // 是否启用内容过滤
  allowedStreams: string[];     // 允许的Stream列表
}

/**
 * 交互对象信息接口（包含mapId）
 *
 * 功能描述：
 * - 扩展InteractionObject接口，添加mapId字段
 * - 用于查询结果返回
 *
 * @since 2025-12-25
 */
export interface InteractionObject extends InteractionObjectConfig {
  mapId: string;                // 所属地图ID
}

/**
 * 配置管理服务类
 *
 * 职责：
 * - 管理地图到Zulip Stream的映射配置
 * - 提供Zulip服务器连接配置
 * - 支持配置文件的热重载
 * - 验证配置的完整性和有效性
 *
 * 主要方法：
 * - loadMapConfig(): 加载地图配置文件
 * - getStreamByMap(): 根据地图ID获取对应的Stream
 * - getZulipConfig(): 获取Zulip服务器配置
 * - validateConfig(): 验证配置文件格式
 * - enableConfigWatcher(): 启用配置文件监控
 *
 * 使用场景：
 * - 系统启动时加载配置
 * - 消息路由时查找Stream映射
 * - 配置文件变更时自动重载
 * - 配置验证和错误处理
 */
@Injectable()
export class ConfigManagerService implements OnModuleDestroy {
  private mapConfigs: Map<string, MapConfig> = new Map();
  private streamToMapIndex: Map<string, string> = new Map(); // Stream名称到mapId的索引
  private zulipConfig: ZulipConfig;
  private fullConfig: ZulipConfiguration;
  private configLoadTime: Date;
  private configWatcher: fs.FSWatcher | null = null;
  private isWatcherEnabled: boolean = false;
  private readonly CONFIG_DIR = this.getConfigDir();
  private readonly MAP_CONFIG_FILE = 'map-config.json';
  private readonly logger = new Logger(ConfigManagerService.name);

  /**
   * 获取配置目录路径
   *
   * 在开发环境中使用 config/zulip
   * 在生产环境中使用 dist/zulip (编译后的位置)
   */
  private getConfigDir(): string {
    const isDevelopment = process.env.NODE_ENV !== 'production';

    if (isDevelopment) {
      // 开发环境：使用源码目录
      return path.join(process.cwd(), 'config', 'zulip');
    } else {
      // 生产环境：使用编译后的目录
      const distConfigPath = path.join(process.cwd(), 'dist', 'zulip');
      const rootConfigPath = path.join(process.cwd(), 'config', 'zulip');

      // 优先使用 dist/zulip，如果不存在则回退到 config/zulip
      if (fs.existsSync(distConfigPath)) {
        return distConfigPath;
      } else if (fs.existsSync(rootConfigPath)) {
        return rootConfigPath;
      } else {
        // 都不存在，使用默认路径
        return distConfigPath;
      }
    }
  }

  constructor() {
    this.logger.log('ConfigManagerService初始化完成');

    // 初始化时加载配置
    this.initializeConfig();
  }

  /**
   * 模块销毁时清理资源
   */
  onModuleDestroy(): void {
    this.disableConfigWatcher();
    this.logger.log('ConfigManagerService资源已清理', {
      service: 'ConfigManagerService',
      timestamp: new Date().toISOString(),
    });
  }

  /**
   * 初始化配置
   *
   * 功能描述：
   * 加载所有配置并进行启动时验证
   *
   * @private
   */
  private async initializeConfig(): Promise<void> {
    try {
      // 加载完整配置
      this.fullConfig = loadZulipConfigFromEnv();

      // 验证配置
      const isProduction = process.env.NODE_ENV === 'production';
      const validationResult = validateZulipConfig(this.fullConfig, isProduction);

      if (!validationResult.valid) {
        this.logger.error('配置验证失败', {
          operation: 'initializeConfig',
          errors: validationResult.errors,
          timestamp: new Date().toISOString(),
        });

        // 非生产环境允许使用默认配置继续
        if (isProduction) {
          throw new Error(`配置验证失败: ${validationResult.errors.join(', ')}`);
        }
      }

      if (validationResult.warnings.length > 0) {
        this.logger.warn('配置验证警告', {
          operation: 'initializeConfig',
          warnings: validationResult.warnings,
          timestamp: new Date().toISOString(),
        });
      }

      await this.loadMapConfig();
      await this.loadZulipConfig();

      this.configLoadTime = new Date();

      this.logger.log('配置初始化完成', {
        operation: 'initializeConfig',
        mapConfigCount: this.mapConfigs.size,
        configLoadTime: this.configLoadTime,
        isProduction,
        timestamp: new Date().toISOString(),
      });

    } catch (error) {
      const err = error as Error;
      this.logger.error('配置初始化失败', {
        operation: 'initializeConfig',
        error: err.message,
        timestamp: new Date().toISOString(),
      }, err.stack);

      // 使用默认配置
      this.loadDefaultConfig();
    }
  }

  /**
   * 加载地图映射配置
   *
   * 功能描述：
   * 从配置文件加载地图到Zulip Stream/Topic的映射关系
   *
   * 处理流程：
   * 1. 读取配置文件
   * 2. 解析JSON配置
   * 3. 验证配置格式
   * 4. 存储到内存映射
   *
   * @returns Promise<void>
   *
   * @throws Error 当配置格式无效时
   * @throws Error 当文件读取失败时
   */
  async loadMapConfig(): Promise<void> {
    this.logger.log('开始加载地图配置', {
      operation: 'loadMapConfig',
      configFile: this.MAP_CONFIG_FILE,
      timestamp: new Date().toISOString(),
    });

    try {
      const configPath = path.join(this.CONFIG_DIR, this.MAP_CONFIG_FILE);

      // 检查配置文件是否存在
      if (!fs.existsSync(configPath)) {
        this.logger.warn('地图配置文件不存在，创建默认配置', {
          operation: 'loadMapConfig',
          configPath,
        });

        await this.createDefaultMapConfig(configPath);
      }

      // 读取配置文件
      const configContent = fs.readFileSync(configPath, 'utf-8');
      const configData = JSON.parse(configContent);

      // 验证配置格式
      if (!configData.maps || !Array.isArray(configData.maps)) {
        throw new Error('配置格式无效：缺少maps数组');
      }

      // 清空现有配置
      this.mapConfigs.clear();
      this.streamToMapIndex.clear();

      // 加载配置到内存
      for (const mapConfig of configData.maps) {
        if (this.validateMapConfig(mapConfig)) {
          this.mapConfigs.set(mapConfig.mapId, mapConfig);
          // 建立Stream到mapId的索引
          this.streamToMapIndex.set(mapConfig.zulipStream.toLowerCase(), mapConfig.mapId);
        } else {
          this.logger.warn('跳过无效的地图配置', {
            operation: 'loadMapConfig',
            mapId: mapConfig.mapId,
          });
        }
      }

      this.logger.log('地图配置加载完成', {
        operation: 'loadMapConfig',
        configCount: this.mapConfigs.size,
        timestamp: new Date().toISOString(),
      });

    } catch (error) {
      const err = error as Error;
      this.logger.error('加载地图配置失败', {
        operation: 'loadMapConfig',
        error: err.message,
        timestamp: new Date().toISOString(),
      }, err.stack);

      throw error;
    }
  }

  /**
   * 加载Zulip配置
   *
   * @returns Promise<void>
   */
  async loadZulipConfig(): Promise<void> {
    this.logger.log('开始加载Zulip配置', {
      operation: 'loadZulipConfig',
      timestamp: new Date().toISOString(),
    });

    try {
      // 从环境变量和配置文件加载配置
      this.zulipConfig = {
        zulipServerUrl: process.env.ZULIP_SERVER_URL || 'https://your-zulip-server.com',
        zulipBotEmail: process.env.ZULIP_BOT_EMAIL || 'bot@example.com',
        zulipBotApiKey: process.env.ZULIP_BOT_API_KEY || '',

        websocketPort: parseInt(process.env.WEBSOCKET_PORT || '3000', 10),
        websocketNamespace: process.env.WEBSOCKET_NAMESPACE || '/game',

        messageRateLimit: parseInt(process.env.MESSAGE_RATE_LIMIT || '10', 10),
        messageMaxLength: parseInt(process.env.MESSAGE_MAX_LENGTH || '1000', 10),

        sessionTimeout: parseInt(process.env.SESSION_TIMEOUT || '60', 10),
        cleanupInterval: parseInt(process.env.CLEANUP_INTERVAL || '5', 10),

        enableContentFilter: process.env.ENABLE_CONTENT_FILTER !== 'false',
        allowedStreams: (process.env.ALLOWED_STREAMS || '').split(',').filter(s => s.trim()),
      };

      this.logger.log('Zulip配置加载完成', {
        operation: 'loadZulipConfig',
        serverUrl: this.zulipConfig.zulipServerUrl,
        rateLimit: this.zulipConfig.messageRateLimit,
        timestamp: new Date().toISOString(),
      });

    } catch (error) {
      const err = error as Error;
      this.logger.error('加载Zulip配置失败', {
        operation: 'loadZulipConfig',
        error: err.message,
        timestamp: new Date().toISOString(),
      }, err.stack);

      throw error;
    }
  }

  /**
   * 根据地图获取对应的Stream
   *
   * 功能描述：
   * 根据地图ID查找对应的Zulip Stream名称
   *
   * @param mapId 地图ID
   * @returns string | null Stream名称，不存在时返回null
   */
  getStreamByMap(mapId: string): string | null {
    if (!mapId || !mapId.trim()) {
      this.logger.debug('获取Stream失败：mapId为空', {
        operation: 'getStreamByMap',
      });
      return null;
    }

    const mapConfig = this.mapConfigs.get(mapId);

    if (!mapConfig) {
      this.logger.debug('未找到地图配置', {
        operation: 'getStreamByMap',
        mapId,
      });
      return null;
    }

    this.logger.debug('获取地图对应Stream', {
      operation: 'getStreamByMap',
      mapId,
      stream: mapConfig.zulipStream,
    });

    return mapConfig.zulipStream;
  }

  /**
   * 根据地图ID获取完整的地图配置
   *
   * 功能描述：
   * 根据地图ID获取完整的地图配置信息
   *
   * @param mapId 地图ID
   * @returns MapConfig | null 地图配置，不存在时返回null
   */
  getMapConfig(mapId: string): MapConfig | null {
    if (!mapId || !mapId.trim()) {
      this.logger.debug('获取地图配置失败：mapId为空', {
        operation: 'getMapConfig',
      });
      return null;
    }

    const mapConfig = this.mapConfigs.get(mapId);

    if (!mapConfig) {
      this.logger.debug('未找到地图配置', {
        operation: 'getMapConfig',
        mapId,
      });
      return null;
    }

    return mapConfig;
  }

  /**
   * 检查地图是否存在
   *
   * 功能描述：
   * 检查指定的地图ID是否在配置中存在
   *
   * @param mapId 地图ID
   * @returns boolean 是否存在
   */
  hasMap(mapId: string): boolean {
    if (!mapId || !mapId.trim()) {
      return false;
    }
    return this.mapConfigs.has(mapId);
  }

  /**
   * 获取所有地图ID列表
   *
   * 功能描述：
   * 获取所有已配置的地图ID列表
   *
   * @returns string[] 地图ID列表
   */
  getAllMapIds(): string[] {
    return Array.from(this.mapConfigs.keys());
  }

  /**
   * 根据Stream名称获取地图ID
   *
   * 功能描述：
   * 根据Zulip Stream名称反向查找对应的地图ID
   *
   * @param streamName Stream名称
   * @returns string | null 地图ID，不存在时返回null
   */
  getMapIdByStream(streamName: string): string | null {
    if (!streamName || !streamName.trim()) {
      return null;
    }
    return this.streamToMapIndex.get(streamName.toLowerCase()) || null;
  }

  /**
   * 根据Stream名称获取地图配置
   *
   * 功能描述：
   * 根据Zulip Stream名称获取完整的地图配置
   *
   * @param streamName Stream名称
   * @returns MapConfig | null 地图配置，不存在时返回null
   */
  getMapConfigByStream(streamName: string): MapConfig | null {
    const mapId = this.getMapIdByStream(streamName);
    if (!mapId) {
      return null;
    }
    return this.mapConfigs.get(mapId) || null;
  }

  /**
   * 获取所有Stream名称列表
   *
   * 功能描述：
   * 获取所有已配置的Zulip Stream名称列表
   *
   * @returns string[] Stream名称列表
   */
  getAllStreams(): string[] {
    return Array.from(this.mapConfigs.values()).map(config => config.zulipStream);
  }

  /**
   * 检查Stream是否存在
   *
   * 功能描述：
   * 检查指定的Stream名称是否在配置中存在
   *
   * @param streamName Stream名称
   * @returns boolean 是否存在
   */
  hasStream(streamName: string): boolean {
    if (!streamName || !streamName.trim()) {
      return false;
    }
    return this.streamToMapIndex.has(streamName.toLowerCase());
  }

  /**
   * 根据Topic名称查找交互对象
   *
   * 功能描述：
   * 在所有地图中查找具有指定Topic名称的交互对象
   *
   * @param topicName Topic名称
   * @returns InteractionObject | null 交互对象，不存在时返回null
   */
  findObjectByTopic(topicName: string): InteractionObject | null {
    if (!topicName || !topicName.trim()) {
      return null;
    }

    const normalizedTopic = topicName.toLowerCase();

    for (const [mapId, config] of this.mapConfigs) {
      const obj = config.interactionObjects.find(
        o => o.zulipTopic.toLowerCase() === normalizedTopic
      );
      if (obj) {
        return {
          ...obj,
          mapId,
        };
      }
    }

    return null;
  }

  /**
   * 获取地图中的所有交互对象
   *
   * 功能描述：
   * 获取指定地图中的所有交互对象列表
   *
   * @param mapId 地图ID
   * @returns InteractionObject[] 交互对象列表
   */
  getObjectsInMap(mapId: string): InteractionObject[] {
    const mapConfig = this.mapConfigs.get(mapId);
    if (!mapConfig) {
      return [];
    }

    return mapConfig.interactionObjects.map(obj => ({
      ...obj,
      mapId,
    }));
  }

  /**
   * 获取配置文件路径
   *
   * 功能描述：
   * 获取地图配置文件的完整路径
   *
   * @returns string 配置文件路径
   */
  getConfigFilePath(): string {
    return path.join(this.CONFIG_DIR, this.MAP_CONFIG_FILE);
  }

  /**
   * 检查配置文件是否存在
   *
   * 功能描述：
   * 检查地图配置文件是否存在于文件系统中
   *
   * @returns boolean 是否存在
   */
  configFileExists(): boolean {
    return fs.existsSync(this.getConfigFilePath());
  }

  /**
   * 根据交互对象获取Topic
   *
   * 功能描述：
   * 根据地图ID和对象ID查找对应的Zulip Topic名称
   *
   * @param mapId 地图ID
   * @param objectId 交互对象ID
   * @returns string | null Topic名称，不存在时返回null
   */
  getTopicByObject(mapId: string, objectId: string): string | null {
    const mapConfig = this.mapConfigs.get(mapId);

    if (!mapConfig) {
      return null;
    }

    const interactionObject = mapConfig.interactionObjects.find(
      obj => obj.objectId === objectId
    );

    if (!interactionObject) {
      this.logger.debug('未找到交互对象配置', {
        operation: 'getTopicByObject',
        mapId,
        objectId,
      });
      return null;
    }

    this.logger.debug('获取交互对象对应Topic', {
      operation: 'getTopicByObject',
      mapId,
      objectId,
      topic: interactionObject.zulipTopic,
    });

    return interactionObject.zulipTopic;
  }

  /**
   * 根据位置查找附近的交互对象
   *
   * @param mapId 地图ID
   * @param x X坐标
   * @param y Y坐标
   * @param radius 搜索半径（默认50像素）
   * @returns InteractionObject | null 交互对象，不存在时返回null
   */
  findNearbyObject(mapId: string, x: number, y: number, radius: number = 50): InteractionObject | null {
    const mapConfig = this.mapConfigs.get(mapId);

    if (!mapConfig) {
      return null;
    }

    for (const obj of mapConfig.interactionObjects) {
      const distance = Math.sqrt(
        Math.pow(obj.position.x - x, 2) + Math.pow(obj.position.y - y, 2)
      );

      if (distance <= radius) {
        return {
          ...obj,
          mapId,
        };
      }
    }

    return null;
  }

  /**
   * 热重载配置
   *
   * 功能描述：
   * 重新加载配置文件，支持运行时配置更新
   *
   * @returns Promise<void>
   */
  async reloadConfig(): Promise<void> {
    this.logger.log('开始热重载配置', {
      operation: 'reloadConfig',
      timestamp: new Date().toISOString(),
    });

    try {
      await this.loadMapConfig();
      await this.loadZulipConfig();

      this.configLoadTime = new Date();

      this.logger.log('配置热重载完成', {
        operation: 'reloadConfig',
        mapConfigCount: this.mapConfigs.size,
        configLoadTime: this.configLoadTime,
        timestamp: new Date().toISOString(),
      });

    } catch (error) {
      const err = error as Error;
      this.logger.error('配置热重载失败', {
        operation: 'reloadConfig',
        error: err.message,
        timestamp: new Date().toISOString(),
      }, err.stack);

      throw error;
    }
  }

  /**
   * 验证配置有效性
   *
   * @returns Promise<{valid: boolean, errors: string[]}>
   */
  async validateConfig(): Promise<{ valid: boolean; errors: string[] }> {
    const errors: string[] = [];

    try {
      // 验证Zulip配置
      if (!this.zulipConfig) {
        errors.push('Zulip配置未加载');
      } else {
        if (!this.zulipConfig.zulipServerUrl) {
          errors.push('缺少Zulip服务器URL');
        }
        if (!this.zulipConfig.zulipBotEmail) {
          errors.push('缺少Zulip机器人邮箱');
        }
        if (!this.zulipConfig.zulipBotApiKey) {
          errors.push('缺少Zulip机器人API Key');
        }
      }

      // 验证地图配置
      if (this.mapConfigs.size === 0) {
        errors.push('没有加载任何地图配置');
      }

      for (const [mapId, config] of this.mapConfigs) {
        if (!this.validateMapConfig(config)) {
          errors.push(`地图配置无效: ${mapId}`);
        }
      }

      const valid = errors.length === 0;

      this.logger.log('配置验证完成', {
        operation: 'validateConfig',
        valid,
        errorCount: errors.length,
        timestamp: new Date().toISOString(),
      });

      return { valid, errors };

    } catch (error) {
      const err = error as Error;
      this.logger.error('配置验证失败', {
        operation: 'validateConfig',
        error: err.message,
        timestamp: new Date().toISOString(),
      }, err.stack);

      return {
        valid: false,
        errors: [...errors, `验证过程出错: ${err.message}`],
      };
    }
  }

  /**
   * 获取Zulip配置
   *
   * @returns ZulipConfig Zulip配置对象
   */
  getZulipConfig(): ZulipConfig {
    return this.zulipConfig;
  }

  /**
   * 获取所有地图配置
   *
   * @returns MapConfig[] 地图配置列表
   */
  getAllMapConfigs(): MapConfig[] {
    return Array.from(this.mapConfigs.values());
  }

  /**
   * 获取配置统计信息
   *
   * @returns 配置统计信息
   */
  getConfigStats(): {
    mapCount: number;
    totalObjects: number;
    configLoadTime: Date;
    isValid: boolean;
  } {
    const totalObjects = Array.from(this.mapConfigs.values())
      .reduce((sum, config) => sum + config.interactionObjects.length, 0);

    return {
      mapCount: this.mapConfigs.size,
      totalObjects,
      configLoadTime: this.configLoadTime,
      isValid: this.mapConfigs.size > 0 && !!this.zulipConfig,
    };
  }

  /**
   * 验证单个地图配置
   *
   * 功能描述：
   * 验证地图配置的完整性和有效性
   *
   * 验证规则：
   * 1. mapId必须存在且为非空字符串
   * 2. mapName必须存在且为非空字符串
   * 3. zulipStream必须存在且为非空字符串
   * 4. interactionObjects必须是数组
   * 5. 每个交互对象必须有有效的objectId、objectName、zulipTopic和position
   * 6. position必须包含有效的x和y坐标（数字类型）
   *
   * @param config 地图配置
   * @returns boolean 是否有效
   * @private
   */
  private validateMapConfig(config: any): boolean {
    // 1. 验证mapId
    if (!config.mapId || typeof config.mapId !== 'string' || !config.mapId.trim()) {
      this.logger.debug('地图配置验证失败：mapId无效', {
        operation: 'validateMapConfig',
        mapId: config.mapId,
      });
      return false;
    }

    // 2. 验证mapName
    if (!config.mapName || typeof config.mapName !== 'string' || !config.mapName.trim()) {
      this.logger.debug('地图配置验证失败：mapName无效', {
        operation: 'validateMapConfig',
        mapId: config.mapId,
        mapName: config.mapName,
      });
      return false;
    }

    // 3. 验证zulipStream
    if (!config.zulipStream || typeof config.zulipStream !== 'string' || !config.zulipStream.trim()) {
      this.logger.debug('地图配置验证失败：zulipStream无效', {
        operation: 'validateMapConfig',
        mapId: config.mapId,
        zulipStream: config.zulipStream,
      });
      return false;
    }

    // 4. 验证interactionObjects是数组
    if (!Array.isArray(config.interactionObjects)) {
      this.logger.debug('地图配置验证失败：interactionObjects不是数组', {
        operation: 'validateMapConfig',
        mapId: config.mapId,
      });
      return false;
    }

    // 5. 验证每个交互对象
    for (const obj of config.interactionObjects) {
      if (!this.validateInteractionObject(obj, config.mapId)) {
        return false;
      }
    }

    return true;
  }

  /**
   * 验证单个交互对象配置
   *
   * 功能描述：
   * 验证交互对象配置的完整性和有效性
   *
   * @param obj 交互对象配置
   * @param mapId 所属地图ID（用于日志）
   * @returns boolean 是否有效
   * @private
   */
  private validateInteractionObject(obj: any, mapId: string): boolean {
    // 验证objectId
    if (!obj.objectId || typeof obj.objectId !== 'string' || !obj.objectId.trim()) {
      this.logger.debug('交互对象验证失败：objectId无效', {
        operation: 'validateInteractionObject',
        mapId,
        objectId: obj.objectId,
      });
      return false;
    }

    // 验证objectName
    if (!obj.objectName || typeof obj.objectName !== 'string' || !obj.objectName.trim()) {
      this.logger.debug('交互对象验证失败：objectName无效', {
        operation: 'validateInteractionObject',
        mapId,
        objectId: obj.objectId,
        objectName: obj.objectName,
      });
      return false;
    }

    // 验证zulipTopic
    if (!obj.zulipTopic || typeof obj.zulipTopic !== 'string' || !obj.zulipTopic.trim()) {
      this.logger.debug('交互对象验证失败：zulipTopic无效', {
        operation: 'validateInteractionObject',
        mapId,
        objectId: obj.objectId,
        zulipTopic: obj.zulipTopic,
      });
      return false;
    }

    // 验证position
    if (!obj.position || typeof obj.position !== 'object') {
      this.logger.debug('交互对象验证失败：position无效', {
        operation: 'validateInteractionObject',
        mapId,
        objectId: obj.objectId,
      });
      return false;
    }

    // 验证position.x
    if (typeof obj.position.x !== 'number' || !Number.isFinite(obj.position.x)) {
      this.logger.debug('交互对象验证失败：position.x无效', {
        operation: 'validateInteractionObject',
        mapId,
        objectId: obj.objectId,
        x: obj.position.x,
      });
      return false;
    }

    // 验证position.y
    if (typeof obj.position.y !== 'number' || !Number.isFinite(obj.position.y)) {
      this.logger.debug('交互对象验证失败：position.y无效', {
        operation: 'validateInteractionObject',
        mapId,
        objectId: obj.objectId,
        y: obj.position.y,
      });
      return false;
    }

    return true;
  }

  /**
   * 获取详细的配置验证结果
   *
   * 功能描述：
   * 对配置进行详细验证，返回所有错误和警告信息
   *
   * @param config 配置对象
   * @returns ConfigValidationResult 验证结果
   */
  validateMapConfigDetailed(config: any): ConfigValidationResult {
    const errors: string[] = [];
    const warnings: string[] = [];

    // 验证mapId
    if (!config.mapId) {
      errors.push('缺少mapId字段');
    } else if (typeof config.mapId !== 'string') {
      errors.push('mapId必须是字符串类型');
    } else if (!config.mapId.trim()) {
      errors.push('mapId不能为空字符串');
    }

    // 验证mapName
    if (!config.mapName) {
      errors.push('缺少mapName字段');
    } else if (typeof config.mapName !== 'string') {
      errors.push('mapName必须是字符串类型');
    } else if (!config.mapName.trim()) {
      errors.push('mapName不能为空字符串');
    }

    // 验证zulipStream
    if (!config.zulipStream) {
      errors.push('缺少zulipStream字段');
    } else if (typeof config.zulipStream !== 'string') {
      errors.push('zulipStream必须是字符串类型');
    } else if (!config.zulipStream.trim()) {
      errors.push('zulipStream不能为空字符串');
    }

    // 验证interactionObjects
    if (!config.interactionObjects) {
      warnings.push('缺少interactionObjects字段，将使用空数组');
    } else if (!Array.isArray(config.interactionObjects)) {
      errors.push('interactionObjects必须是数组类型');
    } else {
      // 验证每个交互对象
      config.interactionObjects.forEach((obj: any, index: number) => {
        const objErrors = this.validateInteractionObjectDetailed(obj, index);
        errors.push(...objErrors);
      });

      // 检查objectId重复
      const objectIds = config.interactionObjects.map((obj: any) => obj.objectId);
      const duplicates = objectIds.filter((id: string, index: number) => objectIds.indexOf(id) !== index);
      if (duplicates.length > 0) {
        warnings.push(`存在重复的objectId: ${[...new Set(duplicates)].join(', ')}`);
      }
    }

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

  /**
   * 验证单个交互对象并返回详细错误
   *
   * @param obj 交互对象
   * @param index 对象索引
   * @returns string[] 错误信息列表
   * @private
   */
  private validateInteractionObjectDetailed(obj: any, index: number): string[] {
    const errors: string[] = [];
    const prefix = `interactionObjects[${index}]`;

    if (!obj.objectId) {
      errors.push(`${prefix}: 缺少objectId字段`);
    } else if (typeof obj.objectId !== 'string' || !obj.objectId.trim()) {
      errors.push(`${prefix}: objectId必须是非空字符串`);
    }

    if (!obj.objectName) {
      errors.push(`${prefix}: 缺少objectName字段`);
    } else if (typeof obj.objectName !== 'string' || !obj.objectName.trim()) {
      errors.push(`${prefix}: objectName必须是非空字符串`);
    }

    if (!obj.zulipTopic) {
      errors.push(`${prefix}: 缺少zulipTopic字段`);
    } else if (typeof obj.zulipTopic !== 'string' || !obj.zulipTopic.trim()) {
      errors.push(`${prefix}: zulipTopic必须是非空字符串`);
    }

    if (!obj.position) {
      errors.push(`${prefix}: 缺少position字段`);
    } else if (typeof obj.position !== 'object') {
      errors.push(`${prefix}: position必须是对象类型`);
    } else {
      if (typeof obj.position.x !== 'number' || !Number.isFinite(obj.position.x)) {
        errors.push(`${prefix}: position.x必须是有效数字`);
      }
      if (typeof obj.position.y !== 'number' || !Number.isFinite(obj.position.y)) {
        errors.push(`${prefix}: position.y必须是有效数字`);
      }
    }

    return errors;
  }

  /**
   * 创建默认地图配置
   *
   * @param configPath 配置文件路径
   * @private
   */
  private async createDefaultMapConfig(configPath: string): Promise<void> {
    const defaultConfig = {
      maps: [
        {
          mapId: 'novice_village',
          mapName: '新手村',
          zulipStream: 'Novice Village',
          interactionObjects: [
            {
              objectId: 'notice_board',
              objectName: '公告板',
              zulipTopic: 'Notice Board',
              position: { x: 100, y: 150 }
            },
            {
              objectId: 'village_well',
              objectName: '村井',
              zulipTopic: 'Village Well',
              position: { x: 200, y: 200 }
            }
          ]
        },
        {
          mapId: 'tavern',
          mapName: '酒馆',
          zulipStream: 'Tavern',
          interactionObjects: [
            {
              objectId: 'bar_counter',
              objectName: '吧台',
              zulipTopic: 'Bar Counter',
              position: { x: 150, y: 100 }
            },
            {
              objectId: 'fireplace',
              objectName: '壁炉',
              zulipTopic: 'Fireplace Chat',
              position: { x: 300, y: 200 }
            }
          ]
        }
      ]
    };

    // 确保配置目录存在
    const configDir = path.dirname(configPath);
    if (!fs.existsSync(configDir)) {
      fs.mkdirSync(configDir, { recursive: true });
    }

    // 写入默认配置
    fs.writeFileSync(configPath, JSON.stringify(defaultConfig, null, 2), 'utf-8');

    this.logger.log('创建默认地图配置', {
      operation: 'createDefaultMapConfig',
      configPath,
      mapCount: defaultConfig.maps.length,
    });
  }

  /**
   * 加载默认配置
   *
   * @private
   */
  private loadDefaultConfig(): void {
    this.logger.warn('使用默认配置', {
      operation: 'loadDefaultConfig',
      timestamp: new Date().toISOString(),
    });

    // 设置默认完整配置
    this.fullConfig = DEFAULT_ZULIP_CONFIG;

    // 设置默认地图配置
    const defaultMapConfig: MapConfig = {
      mapId: 'novice_village',
      mapName: '新手村',
      zulipStream: 'General',
      interactionObjects: [],
    };

    this.mapConfigs.set('novice_village', defaultMapConfig);

    // 设置默认Zulip配置（兼容旧版本）
    this.zulipConfig = {
      zulipServerUrl: 'https://your-zulip-server.com',
      zulipBotEmail: 'bot@example.com',
      zulipBotApiKey: '',
      websocketPort: 3000,
      websocketNamespace: '/game',
      messageRateLimit: 10,
      messageMaxLength: 1000,
      sessionTimeout: 60,
      cleanupInterval: 5,
      enableContentFilter: true,
      allowedStreams: [],
    };

    this.configLoadTime = new Date();
  }

  // ==================== 配置热重载相关方法 ====================

  /**
   * 启用配置文件监听
   *
   * 功能描述：
   * 监听配置文件变化，自动触发配置热重载
   *
   * @returns boolean 是否成功启用
   */
  enableConfigWatcher(): boolean {
    if (this.isWatcherEnabled) {
      this.logger.log('配置文件监听已启用，跳过', {
        operation: 'enableConfigWatcher',
      });
      return true;
    }

    try {
      const configPath = path.join(this.CONFIG_DIR, this.MAP_CONFIG_FILE);

      if (!fs.existsSync(configPath)) {
        this.logger.warn('配置文件不存在，无法启用监听', {
          operation: 'enableConfigWatcher',
          configPath,
        });
        return false;
      }

      this.configWatcher = fs.watch(configPath, (eventType, filename) => {
        if (eventType === 'change') {
          this.logger.log('检测到配置文件变化，触发热重载', {
            operation: 'configWatcher',
            filename,
            eventType,
          });

          // 延迟重载，避免文件写入过程中触发多次
          setTimeout(() => {
            this.reloadConfig().catch(err => {
              this.logger.error('配置热重载失败', {
                operation: 'configWatcher',
                error: (err as Error).message,
              });
            });
          }, 500);
        }
      });

      this.isWatcherEnabled = true;

      this.logger.log('配置文件监听已启用', {
        operation: 'enableConfigWatcher',
        configPath,
        timestamp: new Date().toISOString(),
      });

      return true;

    } catch (error) {
      const err = error as Error;
      this.logger.error('启用配置文件监听失败', {
        operation: 'enableConfigWatcher',
        error: err.message,
        timestamp: new Date().toISOString(),
      }, err.stack);

      return false;
    }
  }

  /**
   * 禁用配置文件监听
   *
   * 功能描述：
   * 停止监听配置文件变化
   */
  disableConfigWatcher(): void {
    if (this.configWatcher) {
      this.configWatcher.close();
      this.configWatcher = null;
      this.isWatcherEnabled = false;

      this.logger.log('配置文件监听已禁用', {
        operation: 'disableConfigWatcher',
        timestamp: new Date().toISOString(),
      });
    }
  }

  /**
   * 检查配置文件监听是否启用
   *
   * @returns boolean 是否启用
   */
  isConfigWatcherEnabled(): boolean {
    return this.isWatcherEnabled;
  }

  /**
   * 获取完整的Zulip配置
   *
   * 功能描述：
   * 获取新版本的完整配置对象
   *
   * @returns ZulipConfiguration 完整配置对象
   */
  getFullConfiguration(): ZulipConfiguration {
    return this.fullConfig || DEFAULT_ZULIP_CONFIG;
  }

  /**
   * 更新配置值
   *
   * 功能描述：
   * 动态更新配置值（不持久化到文件）
   *
   * @param key 配置键路径（如 'message.rateLimit'）
   * @param value 配置值
   * @returns boolean 是否更新成功
   */
  updateConfigValue(key: string, value: any): boolean {
    try {
      const keys = key.split('.');
      let target: any = this.fullConfig;

      for (let i = 0; i < keys.length - 1; i++) {
        if (target[keys[i]] === undefined) {
          this.logger.warn('配置键路径无效', {
            operation: 'updateConfigValue',
            key,
          });
          return false;
        }
        target = target[keys[i]];
      }

      const lastKey = keys[keys.length - 1];
      if (target[lastKey] === undefined) {
        this.logger.warn('配置键不存在', {
          operation: 'updateConfigValue',
          key,
        });
        return false;
      }

      const oldValue = target[lastKey];
      target[lastKey] = value;

      // 同步更新兼容配置
      this.syncLegacyConfig();

      this.logger.log('配置值已更新', {
        operation: 'updateConfigValue',
        key,
        oldValue,
        newValue: value,
        timestamp: new Date().toISOString(),
      });

      return true;

    } catch (error) {
      const err = error as Error;
      this.logger.error('更新配置值失败', {
        operation: 'updateConfigValue',
        key,
        error: err.message,
      });
      return false;
    }
  }

  /**
   * 同步更新兼容配置
   *
   * @private
   */
  private syncLegacyConfig(): void {
    if (!this.fullConfig) return;

    this.zulipConfig = {
      zulipServerUrl: this.fullConfig.server.serverUrl,
      zulipBotEmail: this.fullConfig.server.botEmail,
      zulipBotApiKey: this.fullConfig.server.botApiKey,
      websocketPort: this.fullConfig.websocket.port,
      websocketNamespace: this.fullConfig.websocket.namespace,
      messageRateLimit: this.fullConfig.message.rateLimit,
      messageMaxLength: this.fullConfig.message.maxLength,
      sessionTimeout: this.fullConfig.session.timeout,
      cleanupInterval: this.fullConfig.session.cleanupInterval,
      enableContentFilter: this.fullConfig.message.contentFilterEnabled,
      allowedStreams: this.fullConfig.security.allowedStreams,
    };
  }

  /**
   * 导出当前配置到文件
   *
   * 功能描述：
   * 将当前内存中的地图配置导出到配置文件
   *
   * @param filePath 可选的文件路径，默认为当前配置文件
   * @returns boolean 是否导出成功
   */
  exportMapConfig(filePath?: string): boolean {
    try {
      const targetPath = filePath || path.join(this.CONFIG_DIR, this.MAP_CONFIG_FILE);

      const configData = {
        maps: Array.from(this.mapConfigs.values()),
        version: '1.0.0',
        lastModified: new Date().toISOString(),
      };

      // 确保目录存在
      const configDir = path.dirname(targetPath);
      if (!fs.existsSync(configDir)) {
        fs.mkdirSync(configDir, { recursive: true });
      }

      fs.writeFileSync(targetPath, JSON.stringify(configData, null, 2), 'utf-8');

      this.logger.log('配置导出成功', {
        operation: 'exportMapConfig',
        filePath: targetPath,
        mapCount: this.mapConfigs.size,
        timestamp: new Date().toISOString(),
      });

      return true;

    } catch (error) {
      const err = error as Error;
      this.logger.error('配置导出失败', {
        operation: 'exportMapConfig',
        error: err.message,
        timestamp: new Date().toISOString(),
      }, err.stack);

      return false;
    }
  }
}
