import { GetMessagesHandler } from '../queries/get-messages/get-messages.handler';
import { GetMessagesQuery } from '../queries/get-messages/get-messages.query';

describe('GetMessagesHandler', () => {
  let handler: GetMessagesHandler;
  let mockConversationRepo: {
    findById: ReturnType<typeof vi.fn>;
  };
  let mockMessageRepo: {
    findByConversationId: ReturnType<typeof vi.fn>;
  };

  const conversation = {
    id: 'conv-1',
    participants: [
      { userId: 'user-1' },
      { userId: 'user-2' },
    ],
  };

  const messages = [
    {
      id: 'msg-1',
      conversationId: 'conv-1',
      senderId: 'user-1',
      type: 'TEXT',
      content: 'Hello!',
      metadata: null,
      editedAt: null,
      deletedAt: null,
      createdAt: new Date(),
    },
  ];

  beforeEach(() => {
    mockConversationRepo = {
      findById: vi.fn().mockResolvedValue(conversation),
    };
    mockMessageRepo = {
      findByConversationId: vi.fn().mockResolvedValue(messages),
    };

    handler = new GetMessagesHandler(
      mockConversationRepo as any,
      mockMessageRepo as any,
    );
  });

  it('returns messages for a conversation', async () => {
    const query = new GetMessagesQuery('conv-1', 'user-1', 50);

    const result = await handler.execute(query);

    expect(result).toHaveLength(1);
    expect(mockMessageRepo.findByConversationId).toHaveBeenCalledWith('conv-1', 50, undefined);
  });

  it('throws NotFoundException when conversation does not exist', async () => {
    mockConversationRepo.findById.mockResolvedValue(null);

    const query = new GetMessagesQuery('conv-999', 'user-1');

    await expect(handler.execute(query)).rejects.toThrow();
  });

  it('throws ForbiddenException when user is not a participant', async () => {
    const query = new GetMessagesQuery('conv-1', 'user-3');

    await expect(handler.execute(query)).rejects.toThrow('Bạn không phải là thành viên của hội thoại này');
  });
});
