/**
 * Zulip用户管理服务测试
 * 
 * 功能描述：
 * - 测试UserManagementService的核心功能
 * - 测试用户查询和验证逻辑
 * - 测试错误处理和边界情况
 * - 验证API调用和响应处理
 * 
 * 测试策略：
 * - 模拟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 { UserManagementService, UserQueryRequest, UserValidationRequest } from './user_management.service';
import { IZulipConfigService } from '../zulip_core.interfaces';

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

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

  beforeEach(async () => {
    // 重置fetch模拟
    mockFetch = 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: [
        UserManagementService,
        {
          provide: 'ZULIP_CONFIG_SERVICE',
          useValue: mockConfigService,
        },
      ],
    }).compile();

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

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

  describe('checkUserExists - 检查用户是否存在', () => {
    it('应该正确检查存在的用户', async () => {
      // 模拟API响应
      mockFetch.mockResolvedValueOnce({
        ok: true,
        json: async () => ({
          members: [
            {
              user_id: 1,
              email: 'test@example.com',
              full_name: 'Test User',
              is_active: true,
              is_admin: false,
              is_bot: false,
            },
          ],
        }),
      } as Response);

      const result = await service.checkUserExists('test@example.com');

      expect(result).toBe(true);
      expect(mockFetch).toHaveBeenCalledWith(
        'https://test.zulip.com/api/v1/users',
        expect.objectContaining({
          method: 'GET',
          headers: expect.objectContaining({
            'Authorization': expect.stringContaining('Basic'),
          }),
        })
      );
    });

    it('应该正确检查不存在的用户', async () => {
      // 模拟API响应
      mockFetch.mockResolvedValueOnce({
        ok: true,
        json: async () => ({
          members: [
            {
              user_id: 1,
              email: 'other@example.com',
              full_name: 'Other User',
              is_active: true,
              is_admin: false,
              is_bot: false,
            },
          ],
        }),
      } as Response);

      const result = await service.checkUserExists('test@example.com');

      expect(result).toBe(false);
    });

    it('应该处理无效邮箱', async () => {
      const result = await service.checkUserExists('invalid-email');

      expect(result).toBe(false);
      expect(mockFetch).not.toHaveBeenCalled();
    });

    it('应该处理API调用失败', async () => {
      // 模拟API失败
      mockFetch.mockResolvedValueOnce({
        ok: false,
        status: 500,
        statusText: 'Internal Server Error',
      } as Response);

      const result = await service.checkUserExists('test@example.com');

      expect(result).toBe(false);
    });

    it('应该处理网络异常', async () => {
      // 模拟网络异常
      mockFetch.mockRejectedValueOnce(new Error('Network error'));

      const result = await service.checkUserExists('test@example.com');

      expect(result).toBe(false);
    });
  });

  describe('getUserInfo - 获取用户信息', () => {
    it('应该成功获取用户信息', async () => {
      const request: UserQueryRequest = {
        email: 'test@example.com',
      };

      // 模拟API响应
      mockFetch.mockResolvedValueOnce({
        ok: true,
        json: async () => ({
          members: [
            {
              user_id: 1,
              email: 'test@example.com',
              full_name: 'Test User',
              is_active: true,
              is_admin: false,
              is_bot: false,
            },
          ],
        }),
      } as Response);

      const result = await service.getUserInfo(request);

      expect(result.success).toBe(true);
      expect(result.userId).toBe(1);
      expect(result.email).toBe('test@example.com');
      expect(result.fullName).toBe('Test User');
      expect(result.isActive).toBe(true);
      expect(result.isAdmin).toBe(false);
      expect(result.isBot).toBe(false);
    });

    it('应该处理用户不存在的情况', async () => {
      const request: UserQueryRequest = {
        email: 'nonexistent@example.com',
      };

      // 模拟API响应
      mockFetch.mockResolvedValueOnce({
        ok: true,
        json: async () => ({
          members: [],
        }),
      } as Response);

      const result = await service.getUserInfo(request);

      expect(result.success).toBe(false);
      expect(result.error).toBe('用户不存在');
    });

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

      const result = await service.getUserInfo(request);

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

  describe('validateUserCredentials - 验证用户凭据', () => {
    it('应该成功验证有效的API Key', async () => {
      const request: UserValidationRequest = {
        email: 'test@example.com',
        apiKey: 'valid-api-key',
      };

      // 模拟API Key验证响应（第一个调用）
      mockFetch.mockResolvedValueOnce({
        ok: true,
        json: async () => ({}),
      } as Response);

      // 模拟用户列表API响应（第二个调用）
      mockFetch.mockResolvedValueOnce({
        ok: true,
        json: async () => ({
          members: [
            {
              user_id: 1,
              email: 'test@example.com',
              full_name: 'Test User',
              is_active: true,
              is_admin: false,
              is_bot: false,
            },
          ],
        }),
      } as Response);

      const result = await service.validateUserCredentials(request);

      expect(result.success).toBe(true);
      expect(result.isValid).toBe(true);
      expect(result.userId).toBe(1);
    });

    it('应该拒绝无效的API Key', async () => {
      const request: UserValidationRequest = {
        email: 'test@example.com',
        apiKey: 'invalid-api-key',
      };

      // 模拟API Key验证失败（第一个调用）
      mockFetch.mockResolvedValueOnce({
        ok: false,
        status: 401,
        statusText: 'Unauthorized',
      } as Response);

      const result = await service.validateUserCredentials(request);

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

    it('应该拒绝空的API Key', async () => {
      const request: UserValidationRequest = {
        email: 'test@example.com',
        apiKey: '',
      };

      const result = await service.validateUserCredentials(request);

      expect(result.success).toBe(false);
      expect(result.error).toBe('API Key不能为空');
      expect(mockFetch).not.toHaveBeenCalled();
    });

    it('应该拒绝无效邮箱', async () => {
      const request: UserValidationRequest = {
        email: 'invalid-email',
        apiKey: 'some-api-key',
      };

      const result = await service.validateUserCredentials(request);

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

  describe('getAllUsers - 获取所有用户', () => {
    it('应该成功获取用户列表', async () => {
      // 模拟API响应
      mockFetch.mockResolvedValueOnce({
        ok: true,
        json: async () => ({
          members: [
            {
              user_id: 1,
              email: 'user1@example.com',
              full_name: 'User One',
              is_active: true,
              is_admin: false,
              is_bot: false,
            },
            {
              user_id: 2,
              email: 'user2@example.com',
              full_name: 'User Two',
              is_active: true,
              is_admin: true,
              is_bot: false,
            },
          ],
        }),
      } as Response);

      const result = await service.getAllUsers();

      expect(result.success).toBe(true);
      expect(result.users).toHaveLength(2);
      expect(result.totalCount).toBe(2);
      expect(result.users?.[0]).toEqual({
        userId: 1,
        email: 'user1@example.com',
        fullName: 'User One',
        isActive: true,
        isAdmin: false,
        isBot: false,
      });
    });

    it('应该处理空用户列表', async () => {
      // 模拟API响应
      mockFetch.mockResolvedValueOnce({
        ok: true,
        json: async () => ({
          members: [],
        }),
      } as Response);

      const result = await service.getAllUsers();

      expect(result.success).toBe(true);
      expect(result.users).toHaveLength(0);
      expect(result.totalCount).toBe(0);
    });

    it('应该处理API调用失败', async () => {
      // 模拟API失败
      mockFetch.mockResolvedValueOnce({
        ok: false,
        status: 403,
        statusText: 'Forbidden',
      } as Response);

      const result = await service.getAllUsers();

      expect(result.success).toBe(false);
      expect(result.error).toContain('API调用失败');
    });
  });
});