import { AgentEntity } from '../../domain/entities/agent.entity';
import type { IAgentRepository, AgentDashboardData } from '../../domain/repositories/agent.repository';
import { QualityScore } from '../../domain/value-objects/quality-score.vo';
import { GetAgentDashboardHandler } from '../queries/get-agent-dashboard/get-agent-dashboard.handler';
import { GetAgentDashboardQuery } from '../queries/get-agent-dashboard/get-agent-dashboard.query';

function makeAgent(id: string, userId: string, qualityScore: number): AgentEntity {
  return new AgentEntity(id, {
    userId,
    licenseNumber: null,
    agency: null,
    qualityScore: QualityScore.fromPersistence(qualityScore),
    totalDeals: 0,
    responseTimeAvg: null,
    bio: null,
    serviceAreas: [],
    isVerified: false,
  });
}

describe('GetAgentDashboardHandler', () => {
  let handler: GetAgentDashboardHandler;
  let mockAgentRepo: { [K in keyof IAgentRepository]: ReturnType<typeof vi.fn> };

  beforeEach(() => {
    mockAgentRepo = {
      findByUserId: vi.fn(),
      findById: vi.fn(),
      save: vi.fn(),
      getDashboard: vi.fn(),
      getPublicProfile: vi.fn(),
      getQualityScoreInputs: vi.fn(),
    };

    handler = new GetAgentDashboardHandler(mockAgentRepo as any);
  });

  it('returns dashboard data', async () => {
    mockAgentRepo.findByUserId.mockResolvedValue(makeAgent('agent-1', 'user-1', 85));

    const mockDashboard: AgentDashboardData = {
      agentId: 'agent-1',
      qualityScore: 85,
      totalDeals: 12,
      responseTimeAvg: 600,
      isVerified: true,
      totalLeads: 30,
      leadsByStatus: { NEW: 5, CONTACTED: 10, QUALIFIED: 5, NEGOTIATING: 3, CONVERTED: 5, LOST: 2 },
      conversionRate: 0.167,
      totalInquiries: 45,
      unreadInquiries: 3,
      totalListings: 15,
      activeListings: 10,
      avgReviewRating: 4.5,
      totalReviews: 20,
    };
    mockAgentRepo.getDashboard.mockResolvedValue(mockDashboard);

    const query = new GetAgentDashboardQuery('user-1');
    const result = await handler.execute(query);

    expect(result).toEqual(mockDashboard);
    expect(result.agentId).toBe('agent-1');
    expect(result.qualityScore).toBe(85);
    expect(mockAgentRepo.findByUserId).toHaveBeenCalledWith('user-1');
    expect(mockAgentRepo.getDashboard).toHaveBeenCalledWith('agent-1');
  });

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

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

    await expect(handler.execute(query)).rejects.toThrow(
      'Không tìm thấy thông tin môi giới',
    );
    expect(mockAgentRepo.getDashboard).not.toHaveBeenCalled();
  });
});
