// IM 网关 - 统一消息路由
import type { IMAdapter, IMMessage, IMSendOptions, IMMessageHandler } from './types';
import { createLogger } from '../utils/logger';

const log = createLogger('IMGateway');

export class IMGateway {
  private adapters: Map<string, IMAdapter> = new Map();
  private messageHandlers: IMMessageHandler[] = [];

  registerAdapter(adapter: IMAdapter): void {
    this.adapters.set(adapter.name, adapter);
    
    // 转发消息到全局处理器
    adapter.onMessage(async (message) => {
      log.info(`Message from ${message.channelType}/${message.userId}: ${message.content.slice(0, 50)}...`);
      for (const handler of this.messageHandlers) {
        try {
          await handler(message);
        } catch (error: any) {
          log.error(`Message handler error: ${error.message}`);
        }
      }
    });

    log.info(`IM adapter registered: ${adapter.name}`);
  }

  onMessage(handler: IMMessageHandler): void {
    this.messageHandlers.push(handler);
  }

  async send(options: IMSendOptions): Promise<void> {
    const adapter = this.adapters.get(options.channelType);
    if (!adapter) {
      log.error(`No adapter for channel type: ${options.channelType}`);
      throw new Error(`No adapter for channel type: ${options.channelType}`);
    }

    if (!adapter.isConnected()) {
      log.warn(`Adapter ${options.channelType} not connected, attempting reconnect...`);
      await adapter.connect();
    }

    await adapter.send(options);
    log.debug(`Message sent via ${options.channelType}`);
  }

  async connectAll(): Promise<void> {
    for (const [name, adapter] of this.adapters) {
      try {
        await adapter.connect();
        log.info(`Connected: ${name}`);
      } catch (error: any) {
        log.error(`Failed to connect ${name}: ${error.message}`);
      }
    }
  }

  async disconnectAll(): Promise<void> {
    for (const [name, adapter] of this.adapters) {
      try {
        await adapter.disconnect();
        log.info(`Disconnected: ${name}`);
      } catch (error: any) {
        log.error(`Failed to disconnect ${name}: ${error.message}`);
      }
    }
  }

  getAdapter(name: string): IMAdapter | undefined {
    return this.adapters.get(name);
  }

  getConnectedAdapters(): string[] {
    return Array.from(this.adapters.entries())
      .filter(([, adapter]) => adapter.isConnected())
      .map(([name]) => name);
  }
}
