/**
 * Zulip用户注册服务测试
 * 
 * 功能描述：
 * - 测试UserRegistrationService的核心功能
 * - 测试用户账号创建和验证逻辑
 * - 测试错误处理和边界情况
 * - 验证API Key管理功能
 * 
 * 测试策略：
 * - 模拟Zulip API调用，测试账号创建
 * - 验证用户信息验证的正确性
 * - 测试各种异常场景的处理
 * 
 * 最近修改：
 * - 2026-01-12: 代码规范优化 - 完善测试文件注释规范 (修改者: moyin)
 * 
 * @author angjustinl
 * @version 1.0.1
 * @since 2025-01-06
 * @lastModified 2026-01-12
 */

import { Test, TestingModule } from '@nestjs/testing';
import { UserRegistrationService, UserRegistrationRequest } from './user_registration.service';
import { IZulipConfigService } from '../zulip_core.interfaces';

// 模拟fetch API
global.fetch = jest.fn();

describe('UserRegistrationService', () => {
  let service: UserRegistrationService;
  let mockConfigService: jest.Mocked<IZulipConfigService>;
  let mockFetch: jest.MockedFunction<typeof fetch>;

  beforeEach(async () => {
    // 重置fetch模拟
    mockFetch = global.fetch as jest.MockedFunction<typeof fetch>;
    mockFetch.mockClear();

    // 创建模拟的配置服务
    mockConfigService = {
      getZulipConfig: jest.fn().mockReturnValue({
        zulipServerUrl: 'https://test.zulip.com',
        zulipBotEmail: 'bot@test.com',
        zulipBotApiKey: 'test-api-key',
      }),
      getMapIdByStream: jest.fn(),
      getStreamByMap: jest.fn(),
      getMapConfig: jest.fn(),
      hasMap: jest.fn(),
      getAllMapIds: jest.fn(),
      getMapConfigByStream: jest.fn(),
      getAllStreams: jest.fn(),
      hasStream: jest.fn(),
      findObjectByTopic: jest.fn(),
      getObjectsInMap: jest.fn(),
      getTopicByObject: jest.fn(),
      findNearbyObject: jest.fn(),
      reloadConfig: jest.fn(),
      validateConfig: jest.fn(),
      getAllMapConfigs: jest.fn(),
      getConfigStats: jest.fn(),
      getConfigFilePath: jest.fn(),
      configFileExists: jest.fn(),
      enableConfigWatcher: jest.fn(),
      disableConfigWatcher: jest.fn(),
      isConfigWatcherEnabled: jest.fn(),
      getFullConfiguration: jest.fn(),
      updateConfigValue: jest.fn(),
      exportMapConfig: jest.fn(),
    } as jest.Mocked<IZulipConfigService>;

    const module: TestingModule = await Test.createTestingModule({
      providers: [
        UserRegistrationService,
        {
          provide: 'ZULIP_CONFIG_SERVICE',
          useValue: mockConfigService,
        },
      ],
    }).compile();

    service = module.get<UserRegistrationService>(UserRegistrationService);
  });

  it('应该正确初始化服务', () => {
    expect(service).toBeDefined();
  });

  describe('registerUser - 用户注册', () => {
    it('应该成功注册有效用户', async () => {
      // 模拟检查用户存在性的API调用（用户不存在）
      mockFetch
        .mockResolvedValueOnce({
          ok: true,
          json: async () => ({ members: [] }),
        } as Response)
        // 模拟创建用户的API调用（成功）
        .mockResolvedValueOnce({
          ok: true,
          json: async () => ({ user_id: 123 }),
        } as Response)
        // 模拟生成API Key的调用（成功）
        .mockResolvedValueOnce({
          ok: true,
          json: async () => ({ api_key: 'test-api-key-123' }),
        } as Response);

      const request: UserRegistrationRequest = {
        email: 'test@example.com',
        fullName: 'Test User',
        password: 'password123',
      };

      const result = await service.registerUser(request);

      expect(result.success).toBe(true);
      expect(result.email).toBe(request.email);
      expect(result.userId).toBeDefined();
      expect(result.apiKey).toBeDefined();
      expect(result.error).toBeUndefined();
    });

    it('应该拒绝无效邮箱', async () => {
      const request: UserRegistrationRequest = {
        email: 'invalid-email',
        fullName: 'Test User',
      };

      const result = await service.registerUser(request);

      expect(result.success).toBe(false);
      expect(result.error).toContain('邮箱格式无效');
    });

    it('应该拒绝空邮箱', async () => {
      const request: UserRegistrationRequest = {
        email: '',
        fullName: 'Test User',
      };

      const result = await service.registerUser(request);

      expect(result.success).toBe(false);
      expect(result.error).toContain('邮箱不能为空');
    });

    it('应该拒绝空用户名', async () => {
      const request: UserRegistrationRequest = {
        email: 'test@example.com',
        fullName: '',
      };

      const result = await service.registerUser(request);

      expect(result.success).toBe(false);
      expect(result.error).toContain('用户全名不能为空');
    });

    it('应该拒绝过短的用户名', async () => {
      const request: UserRegistrationRequest = {
        email: 'test@example.com',
        fullName: 'A',
      };

      const result = await service.registerUser(request);

      expect(result.success).toBe(false);
      expect(result.error).toContain('用户全名至少需要2个字符');
    });

    it('应该拒绝过长的用户名', async () => {
      const request: UserRegistrationRequest = {
        email: 'test@example.com',
        fullName: 'A'.repeat(101), // 101个字符
      };

      const result = await service.registerUser(request);

      expect(result.success).toBe(false);
      expect(result.error).toContain('用户全名不能超过100个字符');
    });

    it('应该拒绝过短的密码', async () => {
      const request: UserRegistrationRequest = {
        email: 'test@example.com',
        fullName: 'Test User',
        password: '123', // 只有3个字符
      };

      const result = await service.registerUser(request);

      expect(result.success).toBe(false);
      expect(result.error).toContain('密码至少需要6个字符');
    });

    it('应该接受没有密码的注册', async () => {
      // 模拟检查用户存在性的API调用（用户不存在）
      mockFetch
        .mockResolvedValueOnce({
          ok: true,
          json: async () => ({ members: [] }),
        } as Response)
        // 模拟创建用户的API调用（成功）
        .mockResolvedValueOnce({
          ok: true,
          json: async () => ({ user_id: 124 }),
        } as Response)
        // 模拟生成API Key的调用（成功）
        .mockResolvedValueOnce({
          ok: true,
          json: async () => ({ api_key: 'test-api-key-124' }),
        } as Response);

      const request: UserRegistrationRequest = {
        email: 'test@example.com',
        fullName: 'Test User',
        // 不提供密码
      };

      const result = await service.registerUser(request);

      expect(result.success).toBe(true);
    });

    it('应该拒绝过长的短名称', async () => {
      const request: UserRegistrationRequest = {
        email: 'test@example.com',
        fullName: 'Test User',
        shortName: 'A'.repeat(51), // 51个字符
      };

      const result = await service.registerUser(request);

      expect(result.success).toBe(false);
      expect(result.error).toContain('短名称不能超过50个字符');
    });
  });
});