/**
 * Stream初始化服务
 * 
 * 功能描述：
 * - 在系统启动时检查并创建所有地图对应的Zulip Streams
 * - 确保所有配置的Streams在Zulip服务器上存在
 * - 提供Stream创建和验证功能
 * 
 * 职责分离：
 * - Stream检查层：验证Zulip服务器上Stream的存在性
 * - Stream创建层：自动创建缺失的Stream
 * - 配置同步层：确保本地配置与服务器状态一致
 * 
 * 主要方法：
 * - initializeStreams(): 初始化所有Streams
 * - checkStreamExists(): 检查Stream是否存在
 * - createStream(): 创建Stream
 * 
 * 使用场景：
 * - 系统启动时自动初始化
 * - 配置更新后重新初始化
 * 
 * 最近修改：
 * - 2026-01-12: 代码规范优化 - 修正注释规范和修改记录格式 (修改者: moyin)
 * - 2026-01-07: 代码规范优化 - 更新import路径和注释规范 (修改者: moyin)
 * 
 * @author moyin
 * @version 1.0.2
 * @since 2025-12-25
 * @lastModified 2026-01-12
 */

import { Injectable, Logger, OnModuleInit } from '@nestjs/common';
import { ConfigManagerService } from './config_manager.service';
import { INITIALIZATION_DELAY_MS } from '../zulip_core.constants';

/**
 * Stream初始化服务类
 * 
 * 职责：
 * - 系统启动时自动检查并创建Zulip Streams
 * - 确保所有地图对应的Stream都存在
 * - 验证Stream配置的完整性
 * - 提供Stream初始化状态监控
 * 
 * 主要方法：
 * - onModuleInit(): 模块初始化时自动执行
 * - initializeStreams(): 初始化所有必需的Streams
 * - createStreamIfNotExists(): 检查并创建单个Stream
 * - validateStreamConfig(): 验证Stream配置
 * - getInitializationStatus(): 获取初始化状态
 * 
 * 使用场景：
 * - 系统启动时自动初始化Streams
 * - 确保消息路由的目标Stream存在
 * - 新增地图时自动创建对应Stream
 * - 系统部署和配置验证
 */
@Injectable()
export class StreamInitializerService implements OnModuleInit {
  private readonly logger = new Logger(StreamInitializerService.name);
  private initializationComplete = false;
  
  // 常量定义
  private static readonly INITIALIZATION_DELAY_MS = INITIALIZATION_DELAY_MS; // 初始化延迟时间（毫秒）

  constructor(
    private readonly configManager: ConfigManagerService,
  ) {
    this.logger.log('StreamInitializerService初始化完成');
  }

  /**
   * 模块初始化时自动执行
   */
  async onModuleInit(): Promise<void> {
    // 延迟执行，确保其他服务已初始化
    setTimeout(async () => {
      await this.initializeStreams();
    }, StreamInitializerService.INITIALIZATION_DELAY_MS);
  }

  /**
   * 初始化所有Streams
   * 
   * 功能描述：
   * 检查配置中的所有Streams是否存在，不存在则创建
   * 
   * @returns Promise<{success: boolean, created: string[], existing: string[], failed: string[]}>
   */
  async initializeStreams(): Promise<{
    success: boolean;
    created: string[];
    existing: string[];
    failed: string[];
  }> {
    this.logger.log('开始初始化Zulip Streams', {
      operation: 'initializeStreams',
      timestamp: new Date().toISOString(),
    });

    const created: string[] = [];
    const existing: string[] = [];
    const failed: string[] = [];

    try {
      // 获取所有地图配置
      const mapConfigs = this.configManager.getAllMapConfigs();
      
      if (mapConfigs.length === 0) {
        this.logger.warn('没有找到地图配置，跳过Stream初始化', {
          operation: 'initializeStreams',
        });
        return { success: true, created, existing, failed };
      }

      // 获取所有唯一的Stream名称
      const streamNames = new Set<string>();
      mapConfigs.forEach(config => {
        streamNames.add(config.zulipStream);
      });

      this.logger.log(`找到 ${streamNames.size} 个需要检查的Streams`, {
        operation: 'initializeStreams',
        streamCount: streamNames.size,
        streams: Array.from(streamNames),
      });

      // 检查并创建每个Stream
      for (const streamName of streamNames) {
        try {
          const exists = await this.checkStreamExists(streamName);
          
          if (exists) {
            existing.push(streamName);
            this.logger.log(`Stream已存在: ${streamName}`, {
              operation: 'initializeStreams',
              streamName,
            });
          } else {
            const createResult = await this.createStream(streamName);
            
            if (createResult) {
              created.push(streamName);
              this.logger.log(`Stream创建成功: ${streamName}`, {
                operation: 'initializeStreams',
                streamName,
              });
            } else {
              failed.push(streamName);
              this.logger.warn(`Stream创建失败: ${streamName}`, {
                operation: 'initializeStreams',
                streamName,
              });
            }
          }
        } catch (error) {
          const err = error as Error;
          failed.push(streamName);
          this.logger.error(`处理Stream失败: ${streamName}`, {
            operation: 'initializeStreams',
            streamName,
            error: err.message,
          });
        }
      }

      this.initializationComplete = true;

      const success = failed.length === 0;
      
      this.logger.log('Stream初始化完成', {
        operation: 'initializeStreams',
        success,
        totalStreams: streamNames.size,
        created: created.length,
        existing: existing.length,
        failed: failed.length,
        timestamp: new Date().toISOString(),
      });

      return { success, created, existing, failed };

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

      return { success: false, created, existing, failed };
    }
  }

  /**
   * 检查Stream是否存在
   * 
   * 功能描述：
   * 使用Bot API Key检查指定的Stream是否在Zulip服务器上存在
   * 
   * @param streamName Stream名称
   * @returns Promise<boolean> 是否存在
   */
  private async checkStreamExists(streamName: string): Promise<boolean> {
    try {
      // 获取Zulip配置
      const zulipConfig = this.configManager.getZulipConfig();
      
      if (!zulipConfig.zulipBotApiKey) {
        this.logger.warn('Bot API Key未配置，跳过Stream检查', {
          operation: 'checkStreamExists',
          streamName,
        });
        return false;
      }

      // 动态导入zulip-js
      const zulipModule: any = await import('zulip-js');
      const zulipFactory = zulipModule.default || zulipModule;

      // 创建Bot客户端
      const client = await zulipFactory({
        username: zulipConfig.zulipBotEmail,
        apiKey: zulipConfig.zulipBotApiKey,
        realm: zulipConfig.zulipServerUrl,
      });

      // 获取所有Streams
      const result = await client.streams.retrieve();
      
      if (result.result === 'success' && result.streams) {
        const exists = result.streams.some(
          (stream: any) => stream.name.toLowerCase() === streamName.toLowerCase()
        );
        return exists;
      }

      return false;

    } catch (error) {
      const err = error as Error;
      this.logger.error('检查Stream失败', {
        operation: 'checkStreamExists',
        streamName,
        error: err.message,
      });
      return false;
    }
  }

  /**
   * 创建Stream
   * 
   * 功能描述：
   * 使用Bot API Key在Zulip服务器上创建新的Stream
   * 
   * @param streamName Stream名称
   * @param description Stream描述（可选）
   * @returns Promise<boolean> 是否创建成功
   */
  private async createStream(
    streamName: string,
    description?: string
  ): Promise<boolean> {
    try {
      // 获取Zulip配置
      const zulipConfig = this.configManager.getZulipConfig();
      
      if (!zulipConfig.zulipBotApiKey) {
        this.logger.warn('Bot API Key未配置，无法创建Stream', {
          operation: 'createStream',
          streamName,
        });
        return false;
      }

      // 动态导入zulip-js
      const zulipModule: any = await import('zulip-js');
      const zulipFactory = zulipModule.default || zulipModule;

      // 创建Bot客户端
      const client = await zulipFactory({
        username: zulipConfig.zulipBotEmail,
        apiKey: zulipConfig.zulipBotApiKey,
        realm: zulipConfig.zulipServerUrl,
      });

      // 查找对应的地图配置以获取描述
      const mapConfig = this.configManager.getMapConfigByStream(streamName);
      const streamDescription = description || 
        (mapConfig ? `${mapConfig.mapName} - ${mapConfig.description || 'Game chat channel'}` : 
        `Game chat channel for ${streamName}`);

      // 使用callEndpoint创建Stream
      const result = await client.callEndpoint(
        '/users/me/subscriptions',
        'POST',
        {
          subscriptions: JSON.stringify([
            {
              name: streamName,
              description: streamDescription
            }
          ])
        }
      );

      if (result.result === 'success') {
        this.logger.log('Stream创建成功', {
          operation: 'createStream',
          streamName,
          description: streamDescription,
        });
        return true;
      } else {
        this.logger.warn('Stream创建失败', {
          operation: 'createStream',
          streamName,
          error: result.msg,
        });
        return false;
      }

    } catch (error) {
      const err = error as Error;
      this.logger.error('创建Stream异常', {
        operation: 'createStream',
        streamName,
        error: err.message,
      }, err.stack);
      return false;
    }
  }

  /**
   * 检查初始化是否完成
   * 
   * @returns boolean 是否完成
   */
  isInitializationComplete(): boolean {
    return this.initializationComplete;
  }

  /**
   * 手动触发Stream初始化
   * 
   * 功能描述：
   * 允许手动触发Stream初始化，用于配置更新后重新初始化
   * 
   * @returns Promise<{success: boolean, created: string[], existing: string[], failed: string[]}>
   */
  async reinitializeStreams(): Promise<{
    success: boolean;
    created: string[];
    existing: string[];
    failed: string[];
  }> {
    this.logger.log('手动触发Stream重新初始化', {
      operation: 'reinitializeStreams',
      timestamp: new Date().toISOString(),
    });

    this.initializationComplete = false;
    return await this.initializeStreams();
  }
}
