/**
 * 真实Zulip API测试
 * 
 * 功能描述：
 * - 测试与真实Zulip服务器的HTTP通信
 * - 验证API请求格式、认证和响应处理
 * - 需要真实的Zulip服务器配置才能运行
 * 
 * 注意：
 * - 这些测试需要设置环境变量：ZULIP_SERVER_URL, ZULIP_BOT_EMAIL, ZULIP_BOT_API_KEY
 * - 如果没有配置，测试将被跳过
 * - 测试会在真实服务器上创建消息，请谨慎使用
 * 
 * @author moyin
 * @version 1.0.0
 * @since 2026-01-10
 */

import { Test, TestingModule } from '@nestjs/testing';
import { ZulipClientService, ZulipClientConfig, SendMessageResult } from '../../src/core/zulip_core/services/zulip_client.service';

// 测试配置
const REAL_ZULIP_CONFIG = {
  serverUrl: process.env.ZULIP_SERVER_URL || '',
  botEmail: process.env.ZULIP_BOT_EMAIL || '',
  botApiKey: process.env.ZULIP_BOT_API_KEY || '',
  testStream: process.env.ZULIP_TEST_STREAM || 'test-stream',
  testTopic: process.env.ZULIP_TEST_TOPIC || 'API Test',
};

// 检查是否有真实配置
const hasRealConfig: boolean = !!(REAL_ZULIP_CONFIG.serverUrl && 
                                  REAL_ZULIP_CONFIG.botEmail && 
                                  REAL_ZULIP_CONFIG.botApiKey);

describe('Real Zulip API Integration', () => {
  let service: ZulipClientService;
  let clientConfig: ZulipClientConfig;

  beforeAll(async () => {
    if (!hasRealConfig) {
      console.warn('跳过真实Zulip API测试：缺少环境变量配置');
      console.warn('需要设置: ZULIP_SERVER_URL, ZULIP_BOT_EMAIL, ZULIP_BOT_API_KEY');
      return;
    }

    const module: TestingModule = await Test.createTestingModule({
      providers: [ZulipClientService],
    }).compile();

    service = module.get<ZulipClientService>(ZulipClientService);

    clientConfig = {
      username: REAL_ZULIP_CONFIG.botEmail,
      apiKey: REAL_ZULIP_CONFIG.botApiKey,
      realm: REAL_ZULIP_CONFIG.serverUrl,
    };
  });

  // 如果没有真实配置，跳过所有测试
  const testIf = (condition: boolean) => condition ? it : it.skip;

  describe('API连接测试', () => {
    testIf(hasRealConfig)('应该能够连接到Zulip服务器', async () => {
      const clientInstance = await service.createClient('test-user', clientConfig);
      
      expect(clientInstance).toBeDefined();
      expect(clientInstance.isValid).toBe(true);
      expect(clientInstance.config.realm).toBe(REAL_ZULIP_CONFIG.serverUrl);

      // 清理
      await service.destroyClient(clientInstance);
    }, 10000);

    testIf(hasRealConfig)('应该能够验证API Key', async () => {
      const clientInstance = await service.createClient('test-user', clientConfig);
      
      const isValid = await service.validateApiKey(clientInstance);
      expect(isValid).toBe(true);

      await service.destroyClient(clientInstance);
    }, 10000);

    testIf(hasRealConfig)('应该拒绝无效的API Key', async () => {
      const invalidConfig = {
        ...clientConfig,
        apiKey: 'invalid-api-key-12345',
      };

      await expect(service.createClient('test-user', invalidConfig))
        .rejects.toThrow();
    }, 10000);
  });

  describe('消息发送测试', () => {
    let clientInstance: any;

    beforeEach(async () => {
      if (!hasRealConfig) return;
      
      clientInstance = await service.createClient('test-user', clientConfig);
    });

    afterEach(async () => {
      if (clientInstance) {
        await service.destroyClient(clientInstance);
      }
    });

    testIf(hasRealConfig)('应该能够发送消息到Zulip', async () => {
      const testMessage = `Test message from automated test - ${new Date().toISOString()}`;
      
      const result = await service.sendMessage(
        clientInstance,
        REAL_ZULIP_CONFIG.testStream,
        REAL_ZULIP_CONFIG.testTopic,
        testMessage
      );

      expect(result.success).toBe(true);
      expect(result.messageId).toBeDefined();
      expect(typeof result.messageId).toBe('number');

      console.log(`消息发送成功，ID: ${result.messageId}`);
    }, 15000);

    testIf(hasRealConfig)('应该处理不存在的Stream', async () => {
      const result = await service.sendMessage(
        clientInstance,
        'nonexistent-stream-12345',
        'test-topic',
        'This should fail'
      );

      expect(result.success).toBe(false);
      expect(result.error).toBeDefined();
      console.log(`预期的错误: ${result.error}`);
    }, 10000);

    testIf(hasRealConfig)('应该能够发送包含特殊字符的消息', async () => {
      const specialMessage = `特殊字符测试 🎮🎯🚀 @#$%^&*() - ${new Date().toISOString()}`;
      
      const result = await service.sendMessage(
        clientInstance,
        REAL_ZULIP_CONFIG.testStream,
        REAL_ZULIP_CONFIG.testTopic,
        specialMessage
      );

      expect(result.success).toBe(true);
      expect(result.messageId).toBeDefined();
    }, 10000);

    testIf(hasRealConfig)('应该能够发送Markdown格式的消息', async () => {
      const markdownMessage = `
# Markdown测试消息

**粗体文本** 和 *斜体文本*

- 列表项 1
- 列表项 2

\`代码块\`

> 引用文本

[链接](https://example.com)

时间戳: ${new Date().toISOString()}
      `.trim();
      
      const result = await service.sendMessage(
        clientInstance,
        REAL_ZULIP_CONFIG.testStream,
        REAL_ZULIP_CONFIG.testTopic,
        markdownMessage
      );

      expect(result.success).toBe(true);
      expect(result.messageId).toBeDefined();
    }, 10000);
  });

  describe('事件队列测试', () => {
    let clientInstance: any;

    beforeEach(async () => {
      if (!hasRealConfig) return;
      
      clientInstance = await service.createClient('test-user', clientConfig);
    });

    afterEach(async () => {
      if (clientInstance) {
        await service.destroyClient(clientInstance);
      }
    });

    testIf(hasRealConfig)('应该能够注册事件队列', async () => {
      const result = await service.registerQueue(clientInstance, ['message']);

      expect(result.success).toBe(true);
      expect(result.queueId).toBeDefined();
      expect(result.lastEventId).toBeDefined();
      expect(typeof result.lastEventId).toBe('number');

      console.log(`队列注册成功，ID: ${result.queueId}, 最后事件ID: ${result.lastEventId}`);
    }, 10000);

    testIf(hasRealConfig)('应该能够获取事件', async () => {
      // 先注册队列
      const registerResult = await service.registerQueue(clientInstance, ['message']);
      expect(registerResult.success).toBe(true);

      // 获取事件（非阻塞模式）
      const eventsResult = await service.getEvents(clientInstance, true);
      
      expect(eventsResult.success).toBe(true);
      expect(Array.isArray(eventsResult.events)).toBe(true);

      console.log(`获取到 ${eventsResult.events?.length || 0} 个事件`);
    }, 10000);

    testIf(hasRealConfig)('应该能够注销事件队列', async () => {
      // 先注册队列
      const registerResult = await service.registerQueue(clientInstance, ['message']);
      expect(registerResult.success).toBe(true);

      // 注销队列
      const deregisterResult = await service.deregisterQueue(clientInstance);
      expect(deregisterResult).toBe(true);
      expect(clientInstance.queueId).toBeUndefined();
    }, 10000);
  });

  describe('HTTP请求详细测试', () => {
    testIf(hasRealConfig)('应该发送正确格式的HTTP请求', async () => {
      // 这个测试验证HTTP请求的具体格式
      const clientInstance = await service.createClient('test-user', clientConfig);
      
      // 监听HTTP请求（这需要拦截zulip-js的请求）
      const originalSend = clientInstance.client.messages.send;
      let capturedRequest: any = null;

      clientInstance.client.messages.send = jest.fn().mockImplementation(async (params) => {
        capturedRequest = params;
        return originalSend.call(clientInstance.client.messages, params);
      });

      const testMessage = `HTTP格式测试 - ${new Date().toISOString()}`;
      
      const result = await service.sendMessage(
        clientInstance,
        REAL_ZULIP_CONFIG.testStream,
        REAL_ZULIP_CONFIG.testTopic,
        testMessage
      );

      expect(result.success).toBe(true);
      expect(capturedRequest).toBeDefined();
      expect(capturedRequest.type).toBe('stream');
      expect(capturedRequest.to).toBe(REAL_ZULIP_CONFIG.testStream);
      expect(capturedRequest.subject).toBe(REAL_ZULIP_CONFIG.testTopic);
      expect(capturedRequest.content).toBe(testMessage);

      await service.destroyClient(clientInstance);
    }, 15000);
  });

  describe('错误处理测试', () => {
    testIf(hasRealConfig)('应该处理网络超时', async () => {
      const clientInstance = await service.createClient('test-user', clientConfig);
      
      // 模拟网络超时（通过修改客户端配置或使用无效的服务器地址）
      const timeoutConfig = {
        ...clientConfig,
        realm: 'https://timeout-test.invalid-domain-12345.com',
      };

      try {
        const timeoutClient = await service.createClient('timeout-test', timeoutConfig);
        // 如果到达这里，说明没有超时，跳过测试
        await service.destroyClient(timeoutClient);
        console.log('网络超时测试跳过：连接成功');
      } catch (error) {
        // 预期的超时错误
        expect(error).toBeDefined();
        console.log(`预期的超时错误: ${(error as Error).message}`);
      }

      await service.destroyClient(clientInstance);
    }, 20000);

    testIf(hasRealConfig)('应该处理认证错误', async () => {
      const invalidConfig = {
        ...clientConfig,
        apiKey: 'definitely-invalid-api-key-12345',
      };

      try {
        await service.createClient('auth-test', invalidConfig);
        fail('应该抛出认证错误');
      } catch (error) {
        expect(error).toBeDefined();
        expect((error as Error).message).toContain('API Key验证失败');
        console.log(`预期的认证错误: ${(error as Error).message}`);
      }
    }, 10000);
  });

  describe('性能测试', () => {
    testIf(hasRealConfig)('应该测量消息发送性能', async () => {
      const clientInstance = await service.createClient('perf-test', clientConfig);
      const messageCount = 10; // 减少数量以避免对服务器造成压力
      
      const startTime = Date.now();
      const promises: Promise<SendMessageResult>[] = [];

      for (let i = 0; i < messageCount; i++) {
        promises.push(
          service.sendMessage(
            clientInstance,
            REAL_ZULIP_CONFIG.testStream,
            'Performance Test',
            `Performance test message ${i} - ${new Date().toISOString()}`
          )
        );
      }

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

      // 验证所有消息都成功发送
      results.forEach((result, index) => {
        expect(result.success).toBe(true);
        console.log(`消息 ${index}: ID ${result.messageId}`);
      });

      const avgTime = duration / messageCount;
      console.log(`发送${messageCount}条消息耗时: ${duration}ms, 平均: ${avgTime.toFixed(2)}ms/条`);

      // 性能断言（根据网络情况调整）
      expect(avgTime).toBeLessThan(2000); // 平均每条消息不超过2秒

      await service.destroyClient(clientInstance);
    }, 30000);
  });

  // 清理测试：在所有测试完成后清理测试数据
  describe('清理测试', () => {
    testIf(hasRealConfig)('应该发送清理完成消息', async () => {
      const clientInstance = await service.createClient('cleanup-test', clientConfig);
      
      const cleanupMessage = `
🧹 自动化测试完成 - ${new Date().toISOString()}

本次测试运行的消息已发送完毕。
如果看到此消息，说明Zulip API集成测试成功完成。

测试包括：
- ✅ API连接和认证
- ✅ 消息发送和格式化
- ✅ 事件队列管理
- ✅ 错误处理
- ✅ 性能测试

所有测试消息可以安全删除。
      `.trim();

      const result = await service.sendMessage(
        clientInstance,
        REAL_ZULIP_CONFIG.testStream,
        'Test Cleanup',
        cleanupMessage
      );

      expect(result.success).toBe(true);
      console.log('清理消息发送成功');

      await service.destroyClient(clientInstance);
    }, 10000);
  });
});

// 导出配置检查函数，供其他测试使用
export function hasZulipConfig(): boolean {
  return hasRealConfig;
}

export function getZulipTestConfig() {
  return REAL_ZULIP_CONFIG;
}