/**
 * 聊天消息端到端集成测试
 * 
 * 功能描述：
 * - 测试从WebSocket接收消息到Zulip服务器发送的完整流程
 * - 验证消息路由、过滤、认证等中间环节
 * - 测试真实的网络请求和响应处理
 * 
 * 测试范围：
 * - WebSocket → ChatService → ZulipClientPool → ZulipClient → Zulip API
 * 
 * 更新记录：
 * - 2026-01-14: 重构后更新 - 使用新的四层架构模块
 *   - ChatService 替代 ZulipService
 *   - ChatSessionService 替代 SessionManagerService
 * 
 * @author moyin
 * @version 2.0.0
 * @since 2026-01-10
 * @lastModified 2026-01-14
 */

import { Test, TestingModule } from '@nestjs/testing';
import { INestApplication } from '@nestjs/common';
import { ChatService } from '../../src/business/chat/chat.service';
import { ChatSessionService } from '../../src/business/chat/services/chat_session.service';
import { ZulipClientPoolService } from '../../src/core/zulip_core/services/zulip_client_pool.service';
import { ZulipClientService, ZulipClientInstance } from '../../src/core/zulip_core/services/zulip_client.service';
import { AppModule } from '../../src/app.module';

describe('ChatMessage E2E Integration', () => {
  let app: INestApplication;
  let chatService: ChatService;
  let zulipClientPool: ZulipClientPoolService;
  let zulipClient: ZulipClientService;
  let sessionManager: ChatSessionService;
  
  // 模拟的Zulip客户端
  let mockZulipSdkClient: any;
  
  // 测试数据
  const testUserId = 'test-user-12345';
  const testSocketId = 'ws_test_socket_123';
  const testConfig = {
    username: 'test-bot@example.com',
    apiKey: 'test-api-key-abcdef',
    realm: 'https://test-zulip.example.com',
  };

  beforeAll(async () => {
    const moduleFixture: TestingModule = await Test.createTestingModule({
      imports: [AppModule],
    }).compile();

    app = moduleFixture.createNestApplication();
    
    // 获取服务实例（使用新的四层架构模块）
    chatService = moduleFixture.get<ChatService>(ChatService);
    zulipClientPool = moduleFixture.get<ZulipClientPoolService>(ZulipClientPoolService);
    zulipClient = moduleFixture.get<ZulipClientService>(ZulipClientService);
    sessionManager = moduleFixture.get<ChatSessionService>(ChatSessionService);

    await app.init();
  });

  afterAll(async () => {
    await app.close();
  });

  beforeEach(() => {
    // 创建模拟的zulip-js客户端
    mockZulipSdkClient = {
      config: testConfig,
      users: {
        me: {
          getProfile: jest.fn().mockResolvedValue({
            result: 'success',
            email: testConfig.username,
            full_name: 'Test Bot',
            user_id: 123,
          }),
        },
      },
      messages: {
        send: jest.fn().mockResolvedValue({
          result: 'success',
          id: 12345,
        }),
      },
      queues: {
        register: jest.fn().mockResolvedValue({
          result: 'success',
          queue_id: 'test-queue-123',
          last_event_id: 0,
        }),
        deregister: jest.fn().mockResolvedValue({
          result: 'success',
        }),
      },
      events: {
        retrieve: jest.fn().mockResolvedValue({
          result: 'success',
          events: [],
        }),
      },
    };

    // Mock zulip-js模块
    jest.spyOn(zulipClient as any, 'loadZulipModule').mockResolvedValue(() => mockZulipSdkClient);
  });

  afterEach(() => {
    jest.clearAllMocks();
  });

  describe('完整的聊天消息流程', () => {
    it('应该成功处理从登录到消息发送的完整流程', async () => {
      // 1. 模拟用户登录
      const loginResult = await chatService.handlePlayerLogin({
        socketId: testSocketId,
        token: 'valid-jwt-token', // 这里需要有效的JWT token
      });

      // 验证登录成功（可能需要根据实际JWT验证逻辑调整）
      if (loginResult.success) {
        expect(loginResult.userId).toBeDefined();
        expect(loginResult.sessionId).toBeDefined();

        // 2. 发送聊天消息
        const chatResult = await chatService.sendChatMessage({
          socketId: testSocketId,
          content: 'Hello from E2E test!',
          scope: 'local',
        });

        // 验证消息发送成功
        expect(chatResult.success).toBe(true);
        expect(chatResult.messageId).toBeDefined();

        // 验证Zulip API被正确调用
        expect(mockZulipSdkClient.messages.send).toHaveBeenCalledWith({
          type: 'stream',
          to: expect.any(String), // Stream名称
          subject: expect.any(String), // Topic名称
          content: 'Hello from E2E test!',
        });
      } else {
        // 如果登录失败，跳过测试或使用模拟会话
        console.warn('登录失败，使用模拟会话进行测试');
        
        // 创建模拟会话
        await sessionManager.createSession(
          testSocketId,
          testUserId,
          'test-queue-123',
          'TestUser',
          'whale_port',
          { x: 0, y: 0 }
        );

        // 发送消息
        const chatResult = await chatService.sendChatMessage({
          socketId: testSocketId,
          content: 'Hello from E2E test with mock session!',
          scope: 'local',
        });

        expect(chatResult.success).toBe(true);
      }
    }, 15000);

    it('应该正确处理不同消息范围的路由', async () => {
      // 创建测试会话
      await sessionManager.createSession(
        testSocketId,
        testUserId,
        'test-queue-123',
        'TestUser',
        'whale_port',
        { x: 0, y: 0 }
      );

      // 测试本地消息
      const localResult = await chatService.sendChatMessage({
        socketId: testSocketId,
        content: 'Local message test',
        scope: 'local',
      });

      expect(localResult.success).toBe(true);
      
      // 验证消息被发送到正确的Stream
      const localCall = mockZulipSdkClient.messages.send.mock.calls.find(
        (call: any) => call[0].content === 'Local message test'
      );
      expect(localCall).toBeDefined();
      expect(localCall[0].to).toBe('Whale Port'); // 应该路由到地图对应的Stream

      // 测试全局消息
      const globalResult = await chatService.sendChatMessage({
        socketId: testSocketId,
        content: 'Global message test',
        scope: 'global',
      });

      expect(globalResult.success).toBe(true);
      
      // 验证全局消息路由
      const globalCall = mockZulipSdkClient.messages.send.mock.calls.find(
        (call: any) => call[0].content === 'Global message test'
      );
      expect(globalCall).toBeDefined();
    });

    it('应该处理消息过滤和验证', async () => {
      // 创建测试会话
      await sessionManager.createSession(
        testSocketId,
        testUserId,
        'test-queue-123',
        'TestUser',
        'whale_port',
        { x: 0, y: 0 }
      );

      // 测试正常消息
      const normalResult = await chatService.sendChatMessage({
        socketId: testSocketId,
        content: 'This is a normal message',
        scope: 'local',
      });
      expect(normalResult.success).toBe(true);

      // 测试空消息
      const emptyResult = await chatService.sendChatMessage({
        socketId: testSocketId,
        content: '',
        scope: 'local',
      });
      expect(emptyResult.success).toBe(false);

      // 测试过长消息
      const longMessage = 'A'.repeat(2000); // 假设限制是1000字符
      const longResult = await chatService.sendChatMessage({
        socketId: testSocketId,
        content: longMessage,
        scope: 'local',
      });
      // 根据实际过滤规则验证结果
      console.log('Long message result:', longResult);
    });

    it('应该处理Zulip API错误', async () => {
      // 创建测试会话
      await sessionManager.createSession(
        testSocketId,
        testUserId,
        'test-queue-123',
        'TestUser',
        'whale_port',
        { x: 0, y: 0 }
      );

      // 模拟Zulip API错误
      mockZulipSdkClient.messages.send.mockResolvedValueOnce({
        result: 'error',
        msg: 'Stream does not exist',
        code: 'STREAM_NOT_FOUND',
      });

      const result = await chatService.sendChatMessage({
        socketId: testSocketId,
        content: 'This message will fail',
        scope: 'local',
      });

      // 验证错误处理（根据实际业务逻辑，可能返回成功但记录错误）
      expect(result).toBeDefined();
    });

    it('应该处理网络异常', async () => {
      // 创建测试会话
      await sessionManager.createSession(
        testSocketId,
        testUserId,
        'test-queue-123',
        'TestUser',
        'whale_port',
        { x: 0, y: 0 }
      );

      // 模拟网络异常
      mockZulipSdkClient.messages.send.mockRejectedValueOnce(new Error('Network timeout'));

      const result = await chatService.sendChatMessage({
        socketId: testSocketId,
        content: 'This will timeout',
        scope: 'local',
      });

      // 验证网络异常处理
      expect(result).toBeDefined();
    });
  });

  describe('客户端池管理', () => {
    it('应该正确管理用户的Zulip客户端', async () => {
      // 创建用户客户端
      const clientInstance = await zulipClientPool.createUserClient(testUserId, testConfig);
      
      expect(clientInstance).toBeDefined();
      expect(clientInstance.userId).toBe(testUserId);
      expect(clientInstance.isValid).toBe(true);

      // 验证客户端可以发送消息
      const sendResult = await zulipClientPool.sendMessage(
        testUserId,
        'test-stream',
        'test-topic',
        'Test message from pool'
      );

      expect(sendResult.success).toBe(true);
      expect(mockZulipSdkClient.messages.send).toHaveBeenCalledWith({
        type: 'stream',
        to: 'test-stream',
        subject: 'test-topic',
        content: 'Test message from pool',
      });

      // 清理客户端
      await zulipClientPool.destroyUserClient(testUserId);
    });

    it('应该处理多用户并发', async () => {
      const userIds = ['user1', 'user2', 'user3'];
      const clients: ZulipClientInstance[] = [];

      // 创建多个用户客户端
      for (const userId of userIds) {
        const client = await zulipClientPool.createUserClient(userId, {
          ...testConfig,
          username: `${userId}@example.com`,
        });
        clients.push(client);
      }

      // 并发发送消息
      const sendPromises = userIds.map(userId =>
        zulipClientPool.sendMessage(
          userId,
          'concurrent-stream',
          'concurrent-topic',
          `Message from ${userId}`
        )
      );

      const results = await Promise.all(sendPromises);

      // 验证所有消息都成功发送
      results.forEach(result => {
        expect(result.success).toBe(true);
      });

      // 清理所有客户端
      for (const userId of userIds) {
        await zulipClientPool.destroyUserClient(userId);
      }
    });
  });

  describe('事件队列集成', () => {
    it('应该正确处理事件队列生命周期', async () => {
      // 创建客户端
      const clientInstance = await zulipClientPool.createUserClient(testUserId, testConfig);
      
      // 验证队列已注册
      expect(clientInstance.queueId).toBeDefined();
      expect(mockZulipSdkClient.queues.register).toHaveBeenCalled();

      // 模拟接收事件
      const mockEvents = [
        {
          id: 1,
          type: 'message',
          message: {
            id: 98765,
            sender_email: 'other-user@example.com',
            content: 'Hello from other user',
            stream_id: 1,
            subject: 'Test Topic',
          },
        },
      ];

      mockZulipSdkClient.events.retrieve.mockResolvedValueOnce({
        result: 'success',
        events: mockEvents,
      });

      // 获取事件
      const userClient: ZulipClientInstance | null = await zulipClientPool.getUserClient(testUserId);
      if (userClient) {
        const eventsResult = await zulipClient.getEvents(userClient, true);
        expect(eventsResult.success).toBe(true);
        expect(eventsResult.events).toEqual(mockEvents);
      }

      // 清理
      await zulipClientPool.destroyUserClient(testUserId);
      expect(mockZulipSdkClient.queues.deregister).toHaveBeenCalled();
    });
  });

  describe('性能测试', () => {
    it('应该在高负载下保持性能', async () => {
      const messageCount = 50;
      const startTime = Date.now();

      // 创建测试会话
      await sessionManager.createSession(
        testSocketId,
        testUserId,
        'test-queue-123',
        'TestUser',
        'whale_port',
        { x: 0, y: 0 }
      );

      // 发送大量消息
      const promises = Array.from({ length: messageCount }, (_, i) =>
        chatService.sendChatMessage({
          socketId: testSocketId,
          content: `Performance test message ${i}`,
          scope: 'local',
        })
      );

      const results = await Promise.all(promises);
      const endTime = Date.now();
      const duration = endTime - startTime;

      // 验证所有消息处理完成
      expect(results).toHaveLength(messageCount);
      
      // 性能检查
      const avgTimePerMessage = duration / messageCount;
      console.log(`处理${messageCount}条消息耗时: ${duration}ms, 平均每条: ${avgTimePerMessage.toFixed(2)}ms`);
      
      // 期望平均每条消息处理时间不超过100ms
      expect(avgTimePerMessage).toBeLessThan(100);
    }, 30000);
  });
});
