import { PrismaMessageRepository } from '../repositories/prisma-message.repository';

describe('PrismaMessageRepository', () => {
  let repository: PrismaMessageRepository;
  let mockPrisma: {
    message: {
      create: ReturnType<typeof vi.fn>;
      findMany: ReturnType<typeof vi.fn>;
      findUnique: ReturnType<typeof vi.fn>;
      updateMany: ReturnType<typeof vi.fn>;
    };
  };

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

  beforeEach(() => {
    mockPrisma = {
      message: {
        create: vi.fn().mockResolvedValue(mockMessage),
        findMany: vi.fn().mockResolvedValue([mockMessage]),
        findUnique: vi.fn().mockResolvedValue(mockMessage),
        updateMany: vi.fn().mockResolvedValue({ count: 1 }),
      },
    };
    repository = new PrismaMessageRepository(mockPrisma as any);
  });

  it('creates a message', async () => {
    const result = await repository.create({
      conversationId: 'conv-1',
      senderId: 'user-1',
      type: 'TEXT',
      content: 'Hello!',
    });

    expect(mockPrisma.message.create).toHaveBeenCalledWith({
      data: {
        conversationId: 'conv-1',
        senderId: 'user-1',
        type: 'TEXT',
        content: 'Hello!',
        metadata: undefined,
      },
    });
    expect(result.id).toBe('msg-1');
    expect(result.type).toBe('TEXT');
  });

  it('finds messages by conversation id', async () => {
    const result = await repository.findByConversationId('conv-1', 50);

    expect(result).toHaveLength(1);
    expect(result[0]!.content).toBe('Hello!');
  });

  it('finds message by id', async () => {
    const result = await repository.findById('msg-1');

    expect(result?.id).toBe('msg-1');
  });

  it('returns null when message not found', async () => {
    mockPrisma.message.findUnique.mockResolvedValue(null);

    const result = await repository.findById('msg-999');

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

  it('soft-deletes a message by sender only', async () => {
    await repository.softDelete('msg-1', 'user-1');

    expect(mockPrisma.message.updateMany).toHaveBeenCalledWith({
      where: { id: 'msg-1', senderId: 'user-1' },
      data: { deletedAt: expect.any(Date) },
    });
  });
});
