import type { AgentPublicProfileData, IAgentRepository } from '../../domain/repositories/agent.repository';
import { GetAgentPublicProfileHandler } from '../queries/get-agent-public-profile/get-agent-public-profile.handler';
import { GetAgentPublicProfileQuery } from '../queries/get-agent-public-profile/get-agent-public-profile.query';

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

  const mockProfile: AgentPublicProfileData = {
    id: 'agent-1',
    fullName: 'Nguyễn Văn A',
    avatarUrl: 'https://example.com/avatar.jpg',
    phone: '0901234567',
    email: 'agent@example.com',
    agency: 'Công ty BĐS ABC',
    licenseNumber: 'BDS-001',
    bio: 'Chuyên viên bất động sản khu vực Quận 7',
    qualityScore: 85,
    totalDeals: 50,
    isVerified: true,
    serviceAreas: ['Quận 7', 'Quận 2', 'Thủ Đức'],
    memberSince: '2024-01-15',
    activeListings: [
      {
        id: 'listing-1',
        transactionType: 'SALE',
        priceVND: '5000000000',
        status: 'ACTIVE',
        property: {
          id: 'prop-1',
          title: 'Căn hộ cao cấp Quận 7',
          propertyType: 'APARTMENT',
          address: '123 Nguyễn Hữu Thọ',
          district: 'Quận 7',
          city: 'TP.HCM',
          areaM2: 75,
          bedrooms: 2,
          bathrooms: 2,
          imageUrl: 'https://example.com/image.jpg',
        },
      },
    ],
    avgReviewRating: 4.5,
    totalReviews: 20,
  };

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

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

  it('returns full public profile for an agent', async () => {
    mockAgentRepo.getPublicProfile.mockResolvedValue(mockProfile);

    const query = new GetAgentPublicProfileQuery('agent-1');
    const result = await handler.execute(query);

    expect(result).toEqual(mockProfile);
    expect(result!.id).toBe('agent-1');
    expect(result!.fullName).toBe('Nguyễn Văn A');
    expect(result!.qualityScore).toBe(85);
    expect(result!.activeListings).toHaveLength(1);
    expect(result!.serviceAreas).toContain('Quận 7');
    expect(mockAgentRepo.getPublicProfile).toHaveBeenCalledWith('agent-1');
  });

  it('returns null when agent does not exist', async () => {
    mockAgentRepo.getPublicProfile.mockResolvedValue(null);

    const query = new GetAgentPublicProfileQuery('nonexistent-agent');
    const result = await handler.execute(query);

    expect(result).toBeNull();
    expect(mockAgentRepo.getPublicProfile).toHaveBeenCalledWith('nonexistent-agent');
  });

  it('returns profile with empty active listings', async () => {
    const profileNoListings: AgentPublicProfileData = {
      ...mockProfile,
      activeListings: [],
      totalDeals: 0,
    };
    mockAgentRepo.getPublicProfile.mockResolvedValue(profileNoListings);

    const query = new GetAgentPublicProfileQuery('agent-1');
    const result = await handler.execute(query);

    expect(result!.activeListings).toHaveLength(0);
    expect(result!.totalDeals).toBe(0);
  });

  it('returns profile with null optional fields', async () => {
    const profileMinimal: AgentPublicProfileData = {
      ...mockProfile,
      avatarUrl: null,
      email: null,
      agency: null,
      licenseNumber: null,
      bio: null,
    };
    mockAgentRepo.getPublicProfile.mockResolvedValue(profileMinimal);

    const query = new GetAgentPublicProfileQuery('agent-1');
    const result = await handler.execute(query);

    expect(result!.avatarUrl).toBeNull();
    expect(result!.email).toBeNull();
    expect(result!.agency).toBeNull();
    expect(result!.licenseNumber).toBeNull();
    expect(result!.bio).toBeNull();
    expect(result!.fullName).toBe('Nguyễn Văn A');
  });

  it('returns profile for unverified agent with zero reviews', async () => {
    const unverifiedProfile: AgentPublicProfileData = {
      ...mockProfile,
      isVerified: false,
      avgReviewRating: 0,
      totalReviews: 0,
      qualityScore: 0,
    };
    mockAgentRepo.getPublicProfile.mockResolvedValue(unverifiedProfile);

    const query = new GetAgentPublicProfileQuery('agent-new');
    const result = await handler.execute(query);

    expect(result!.isVerified).toBe(false);
    expect(result!.avgReviewRating).toBe(0);
    expect(result!.totalReviews).toBe(0);
    expect(result!.qualityScore).toBe(0);
  });
});
