/**
 * 聊天控制器测试
 * 
 * 功能描述：
 * - 测试聊天消息发送功能
 * - 验证消息过滤和验证逻辑
 * - 测试错误处理和异常情况
 * - 验证WebSocket消息广播功能
 * 
 * 测试范围：
 * - 消息发送API测试
 * - 参数验证测试
 * - 错误处理测试
 * - 业务逻辑验证
 * 
 * 最近修改：
 * - 2026-01-12: Bug修复 - 修复测试用例中的方法名和DTO结构 (修改者: moyin)
 * - 2026-01-12: 代码规范优化 - 创建测试文件，确保控制器功能的测试覆盖 (修改者: moyin)
 * 
 * @author moyin
 * @version 1.0.1
 * @since 2026-01-12
 * @lastModified 2026-01-12
 */

import { Test, TestingModule } from '@nestjs/testing';
import { HttpException, HttpStatus } from '@nestjs/common';
import { ChatController } from './chat.controller';
import { ZulipService } from './zulip.service';
import { MessageFilterService } from './services/message_filter.service';
import { CleanWebSocketGateway } from './clean_websocket.gateway';
import { JwtAuthGuard } from '../../gateway/auth/jwt_auth.guard';

// Mock JwtAuthGuard
const mockJwtAuthGuard = {
  canActivate: jest.fn(() => true),
};

describe('ChatController', () => {
  let controller: ChatController;
  let zulipService: jest.Mocked<ZulipService>;
  let messageFilterService: jest.Mocked<MessageFilterService>;
  let websocketGateway: jest.Mocked<CleanWebSocketGateway>;

  beforeEach(async () => {
    const mockZulipService = {
      sendChatMessage: jest.fn(),
    };

    const mockMessageFilterService = {
      validateMessage: jest.fn(),
    };

    const mockWebSocketGateway = {
      broadcastToRoom: jest.fn(),
      getActiveConnections: jest.fn(),
    };

    const module: TestingModule = await Test.createTestingModule({
      controllers: [ChatController],
      providers: [
        {
          provide: ZulipService,
          useValue: mockZulipService,
        },
        {
          provide: MessageFilterService,
          useValue: mockMessageFilterService,
        },
        {
          provide: CleanWebSocketGateway,
          useValue: mockWebSocketGateway,
        },
        {
          provide: JwtAuthGuard,
          useValue: mockJwtAuthGuard,
        },
      ],
    })
    .overrideGuard(JwtAuthGuard)
    .useValue(mockJwtAuthGuard)
    .compile();

    controller = module.get<ChatController>(ChatController);
    zulipService = module.get(ZulipService);
    messageFilterService = module.get(MessageFilterService);
    websocketGateway = module.get(CleanWebSocketGateway);
  });

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

  describe('sendMessage', () => {
    const validMessageDto = {
      content: 'Hello, world!',
      stream: 'general',
      topic: 'chat',
      userId: 'user123',
      scope: 'local',
    };

    it('should reject REST API message sending and suggest WebSocket', async () => {
      // Act & Assert
      await expect(controller.sendMessage(validMessageDto)).rejects.toThrow(
        new HttpException(
          '聊天消息发送需要通过 WebSocket 连接。请使用 WebSocket 接口：wss://whaletownend.xinghangee.icu',
          HttpStatus.BAD_REQUEST,
        )
      );
    });

    it('should log the REST API request attempt', async () => {
      // Arrange
      const loggerSpy = jest.spyOn(controller['logger'], 'log');

      // Act
      try {
        await controller.sendMessage(validMessageDto);
      } catch (error) {
        // Expected to throw
      }

      // Assert
      expect(loggerSpy).toHaveBeenCalledWith('收到REST API聊天消息发送请求', {
        operation: 'sendMessage',
        content: validMessageDto.content.substring(0, 50),
        scope: validMessageDto.scope,
        timestamp: expect.any(String),
      });
    });

    it('should handle different message content lengths', async () => {
      // Arrange
      const longMessageDto = {
        ...validMessageDto,
        content: 'a'.repeat(100), // Long message
      };

      // Act & Assert
      await expect(controller.sendMessage(longMessageDto)).rejects.toThrow(HttpException);
    });

    it('should handle empty message content', async () => {
      // Arrange
      const emptyMessageDto = { ...validMessageDto, content: '' };

      // Act & Assert
      await expect(controller.sendMessage(emptyMessageDto)).rejects.toThrow(HttpException);
    });
  });

  describe('Error Handling', () => {
    it('should always throw HttpException for REST API requests', async () => {
      // Arrange
      const validMessageDto = {
        content: 'Hello, world!',
        stream: 'general',
        topic: 'chat',
        userId: 'user123',
        scope: 'local',
      };

      // Act & Assert
      await expect(controller.sendMessage(validMessageDto)).rejects.toThrow(HttpException);
    });

    it('should log error when REST API is used', async () => {
      // Arrange
      const validMessageDto = {
        content: 'Hello, world!',
        stream: 'general',
        topic: 'chat',
        userId: 'user123',
        scope: 'local',
      };

      const loggerSpy = jest.spyOn(controller['logger'], 'error');

      // Act
      try {
        await controller.sendMessage(validMessageDto);
      } catch (error) {
        // Expected to throw
      }

      // Assert
      expect(loggerSpy).toHaveBeenCalledWith('REST API消息发送失败', {
        operation: 'sendMessage',
        error: expect.any(String),
        timestamp: expect.any(String),
      });
    });
  });
});