import type { ILeadRepository } from '../../domain/repositories/lead.repository';
import { GetLeadsByAgentHandler } from '../queries/get-leads-by-agent/get-leads-by-agent.handler';
import { GetLeadsByAgentQuery } from '../queries/get-leads-by-agent/get-leads-by-agent.query';

describe('GetLeadsByAgentHandler', () => {
  let handler: GetLeadsByAgentHandler;
  let mockLeadRepo: { [K in keyof ILeadRepository]: ReturnType<typeof vi.fn> };
  let mockPrisma: {
    agent: { findUnique: ReturnType<typeof vi.fn> };
  };

  beforeEach(() => {
    mockLeadRepo = {
      findById: vi.fn(),
      save: vi.fn(),
      update: vi.fn(),
      delete: vi.fn(),
      findByAgent: vi.fn(),
      getStatsByAgent: vi.fn(),
    };

    mockPrisma = {
      agent: { findUnique: vi.fn() },
    };

    handler = new GetLeadsByAgentHandler(
      mockLeadRepo as any,
      mockPrisma as any,
    );
  });

  it('returns paginated results', async () => {
    mockPrisma.agent.findUnique.mockResolvedValue({ id: 'agent-1' });

    const mockResult = {
      data: [
        {
          id: 'lead-1',
          agentId: 'agent-1',
          name: 'Nguyễn Văn A',
          phone: '0901234567',
          email: null,
          source: 'WEBSITE',
          score: 75,
          status: 'NEW',
          createdAt: new Date(),
        },
      ],
      total: 1,
      page: 1,
      limit: 20,
      totalPages: 1,
    };
    mockLeadRepo.findByAgent.mockResolvedValue(mockResult);

    const query = new GetLeadsByAgentQuery('user-1', null, 1, 20);
    const result = await handler.execute(query);

    expect(result).toEqual(mockResult);
    expect(result.data).toHaveLength(1);
    expect(mockLeadRepo.findByAgent).toHaveBeenCalledWith('agent-1', null, 1, 20);
  });

  it('passes status filter to repository', async () => {
    mockPrisma.agent.findUnique.mockResolvedValue({ id: 'agent-1' });
    mockLeadRepo.findByAgent.mockResolvedValue({
      data: [],
      total: 0,
      page: 1,
      limit: 20,
      totalPages: 0,
    });

    const query = new GetLeadsByAgentQuery('user-1', 'CONTACTED', 1, 20);
    await handler.execute(query);

    expect(mockLeadRepo.findByAgent).toHaveBeenCalledWith('agent-1', 'CONTACTED', 1, 20);
  });

  it('throws NotFoundException when agent not found', async () => {
    mockPrisma.agent.findUnique.mockResolvedValue(null);

    const query = new GetLeadsByAgentQuery('not-an-agent');

    await expect(handler.execute(query)).rejects.toThrow(
      "Agent with id 'not-an-agent' not found",
    );
    expect(mockLeadRepo.findByAgent).not.toHaveBeenCalled();
  });
});
