/**
 * Zulip账号管理控制器测试
 * 
 * 功能描述：
 * - 测试Zulip账号关联管理功能
 * - 验证账号创建和验证逻辑
 * - 测试账号状态管理和更新
 * - 验证错误处理和异常情况
 * 
 * 测试范围：
 * - 账号关联API测试
 * - 账号验证功能测试
 * - 状态管理测试
 * - 错误处理测试
 * 
 * 最近修改：
 * - 2026-01-12: 测试修复 - 修正测试方法名称和Mock配置，确保与实际控制器方法匹配 (修改者: moyin)
 * - 2026-01-12: 代码规范优化 - 创建测试文件，确保Zulip账号管理控制器功能的测试覆盖 (修改者: moyin)
 * 
 * @author moyin
 * @version 1.1.0
 * @since 2026-01-12
 * @lastModified 2026-01-12
 */

import { Test, TestingModule } from '@nestjs/testing';
import { HttpException, HttpStatus } from '@nestjs/common';
import { ZulipAccountsController } from './zulip_accounts.controller';
import { JwtAuthGuard } from '../auth/jwt_auth.guard';
import { AppLoggerService } from '../../core/utils/logger/logger.service';
import { ZulipAccountsBusinessService } from '../../business/zulip/services/zulip_accounts_business.service';

describe('ZulipAccountsController', () => {
  let controller: ZulipAccountsController;
  let zulipAccountsService: jest.Mocked<any>;

  beforeEach(async () => {
    const mockZulipAccountsService = {
      create: jest.fn(),
      findMany: jest.fn(),
      findById: jest.fn(),
      findByGameUserId: jest.fn(),
      findByZulipUserId: jest.fn(),
      findByZulipEmail: jest.fn(),
      update: jest.fn(),
      updateByGameUserId: jest.fn(),
      delete: jest.fn(),
      deleteByGameUserId: jest.fn(),
      findAccountsNeedingVerification: jest.fn(),
      findErrorAccounts: jest.fn(),
      batchUpdateStatus: jest.fn(),
      getStatusStatistics: jest.fn(),
      verifyAccount: jest.fn(),
      existsByEmail: jest.fn(),
      existsByZulipUserId: jest.fn(),
    };

    const module: TestingModule = await Test.createTestingModule({
      controllers: [ZulipAccountsController],
      providers: [
        { provide: 'ZulipAccountsService', useValue: mockZulipAccountsService },
        { provide: AppLoggerService, useValue: {
          info: jest.fn(),
          error: jest.fn(),
          bindRequest: jest.fn().mockReturnValue({
            info: jest.fn(),
            error: jest.fn(),
          }),
        }},
      ],
    })
    .overrideGuard(JwtAuthGuard)
    .useValue({ canActivate: () => true })
    .compile();

    controller = module.get<ZulipAccountsController>(ZulipAccountsController);
    zulipAccountsService = module.get('ZulipAccountsService');
  });

  describe('Controller Initialization', () => {
    it('should be defined', () => {
      expect(controller).toBeDefined();
    });

    it('should have zulip accounts service dependency', () => {
      expect(zulipAccountsService).toBeDefined();
    });
  });

  describe('create', () => {
    const validCreateDto = {
      gameUserId: 'game123',
      zulipUserId: 456,
      zulipEmail: 'user@example.com',
      zulipFullName: 'Test User',
      zulipApiKeyEncrypted: 'encrypted_api_key_123',
      status: 'active' as const,
    };

    it('should create Zulip account successfully', async () => {
      // Arrange
      const expectedResult = {
        id: 'acc123',
        gameUserId: validCreateDto.gameUserId,
        zulipUserId: validCreateDto.zulipUserId,
        zulipEmail: validCreateDto.zulipEmail,
        zulipFullName: validCreateDto.zulipFullName,
        status: 'active',
        retryCount: 0,
        createdAt: new Date().toISOString(),
        updatedAt: new Date().toISOString(),
      };

      zulipAccountsService.create.mockResolvedValue(expectedResult);

      // Act
      const result = await controller.create({} as any, validCreateDto);

      // Assert
      expect(result).toEqual(expectedResult);
      expect(zulipAccountsService.create).toHaveBeenCalledWith(validCreateDto);
    });

    it('should handle service errors during account creation', async () => {
      // Arrange
      zulipAccountsService.create.mockRejectedValue(
        new Error('Database error')
      );

      // Act & Assert
      await expect(controller.create({} as any, validCreateDto)).rejects.toThrow();
    });
  });

  describe('findByGameUserId', () => {
    const gameUserId = 'game123';

    it('should return account information', async () => {
      // Arrange
      const expectedInfo = {
        id: 'acc123',
        gameUserId: gameUserId,
        zulipUserId: 456,
        zulipEmail: 'user@example.com',
        status: 'active',
        createdAt: new Date().toISOString(),
        updatedAt: new Date().toISOString(),
      };

      zulipAccountsService.findByGameUserId.mockResolvedValue(expectedInfo);

      // Act
      const result = await controller.findByGameUserId(gameUserId, false);

      // Assert
      expect(result).toEqual(expectedInfo);
      expect(zulipAccountsService.findByGameUserId).toHaveBeenCalledWith(gameUserId, false);
    });

    it('should handle account not found', async () => {
      // Arrange
      zulipAccountsService.findByGameUserId.mockResolvedValue(null);

      // Act
      const result = await controller.findByGameUserId(gameUserId, false);

      // Assert
      expect(result).toBeNull();
    });

    it('should handle service errors', async () => {
      // Arrange
      zulipAccountsService.findByGameUserId.mockRejectedValue(
        new Error('Database error')
      );

      // Act & Assert
      await expect(controller.findByGameUserId(gameUserId, false)).rejects.toThrow();
    });
  });

  describe('deleteByGameUserId', () => {
    const gameUserId = 'game123';

    it('should delete account successfully', async () => {
      // Arrange
      zulipAccountsService.deleteByGameUserId.mockResolvedValue(undefined);

      // Act
      const result = await controller.deleteByGameUserId(gameUserId);

      // Assert
      expect(result).toEqual({ success: true, message: '删除成功' });
      expect(zulipAccountsService.deleteByGameUserId).toHaveBeenCalledWith(gameUserId);
    });

    it('should handle account not found during deletion', async () => {
      // Arrange
      zulipAccountsService.deleteByGameUserId.mockRejectedValue(
        new Error('Account not found')
      );

      // Act & Assert
      await expect(controller.deleteByGameUserId(gameUserId)).rejects.toThrow();
    });
  });

  describe('getStatusStatistics', () => {
    it('should return account statistics', async () => {
      // Arrange
      const expectedStats = {
        total: 100,
        active: 80,
        inactive: 15,
        suspended: 3,
        error: 2,
      };

      zulipAccountsService.getStatusStatistics.mockResolvedValue(expectedStats);

      // Act
      const result = await controller.getStatusStatistics({} as any);

      // Assert
      expect(result).toEqual(expectedStats);
      expect(zulipAccountsService.getStatusStatistics).toHaveBeenCalled();
    });

    it('should handle service errors', async () => {
      // Arrange
      zulipAccountsService.getStatusStatistics.mockRejectedValue(
        new Error('Database error')
      );

      // Act & Assert
      await expect(controller.getStatusStatistics({} as any)).rejects.toThrow();
    });
  });

  describe('verifyAccount', () => {
    const verifyDto = { gameUserId: 'game123' };

    it('should verify account successfully', async () => {
      // Arrange
      const validationResult = {
        isValid: true,
        gameUserId: verifyDto.gameUserId,
        zulipUserId: 456,
        status: 'active',
        lastValidated: new Date().toISOString(),
      };

      zulipAccountsService.verifyAccount.mockResolvedValue(validationResult);

      // Act
      const result = await controller.verifyAccount(verifyDto);

      // Assert
      expect(result).toEqual(validationResult);
      expect(zulipAccountsService.verifyAccount).toHaveBeenCalledWith(verifyDto.gameUserId);
    });

    it('should handle invalid account', async () => {
      // Arrange
      const validationResult = {
        isValid: false,
        gameUserId: verifyDto.gameUserId,
        error: 'Account suspended',
        lastValidated: new Date().toISOString(),
      };

      zulipAccountsService.verifyAccount.mockResolvedValue(validationResult);

      // Act
      const result = await controller.verifyAccount(verifyDto);

      // Assert
      expect(result).toEqual(validationResult);
      expect(result.isValid).toBe(false);
    });

    it('should handle validation errors', async () => {
      // Arrange
      zulipAccountsService.verifyAccount.mockRejectedValue(
        new Error('Validation service error')
      );

      // Act & Assert
      await expect(controller.verifyAccount(verifyDto)).rejects.toThrow();
    });
  });

  describe('checkEmailExists', () => {
    const email = 'user@example.com';

    it('should check if email exists', async () => {
      // Arrange
      zulipAccountsService.existsByEmail.mockResolvedValue(false);

      // Act
      const result = await controller.checkEmailExists(email);

      // Assert
      expect(result).toEqual({ exists: false, email });
      expect(zulipAccountsService.existsByEmail).toHaveBeenCalledWith(email, undefined);
    });

    it('should handle service errors when checking email', async () => {
      // Arrange
      zulipAccountsService.existsByEmail.mockRejectedValue(
        new Error('Database error')
      );

      // Act & Assert
      await expect(controller.checkEmailExists(email)).rejects.toThrow();
    });
  });

  describe('Error Handling', () => {
    it('should handle service unavailable errors', async () => {
      // Arrange
      zulipAccountsService.findByGameUserId.mockRejectedValue(
        new Error('Service unavailable')
      );

      // Act & Assert
      await expect(controller.findByGameUserId('game123', false)).rejects.toThrow();
    });

    it('should handle malformed request data', async () => {
      // Arrange
      const malformedDto = { invalid: 'data' };

      // Act & Assert
      await expect(controller.create({} as any, malformedDto as any)).rejects.toThrow();
    });
  });
});