import { render, screen } from '@testing-library/react';
import { describe, expect, it, vi } from 'vitest';
import type { ListingDetail } from '@/lib/listings-api';
import { ListingDetailClient } from '../listing-detail-client';

// Mock next/image
vi.mock('next/image', () => ({
  default: (props: Record<string, unknown>) => <img {...props} />,
}));

// Mock next/link
vi.mock('next/link', () => ({
  default: ({ children, href }: { children: React.ReactNode; href: string }) => (
    <a href={href}>{children}</a>
  ),
}));

// Mock next/dynamic to render children directly
vi.mock('next/dynamic', () => ({
  default: () => {
    const DynamicComponent = () => <div data-testid="listing-map">Map placeholder</div>;
    DynamicComponent.displayName = 'DynamicListingMap';
    return DynamicComponent;
  },
}));

// Mock AddToCompareButton
vi.mock('@/components/comparison/add-to-compare-button', () => ({
  AddToCompareButton: ({ listingId }: { listingId: string }) => (
    <button data-testid={`compare-btn-${listingId}`}>Compare</button>
  ),
}));

// Mock ImageGallery
vi.mock('@/components/listings/image-gallery', () => ({
  ImageGallery: () => <div data-testid="image-gallery">Gallery</div>,
}));

// Mock AiEstimateButton
vi.mock('@/components/valuation/ai-estimate-button', () => ({
  AiEstimateButton: ({ listingId }: { listingId: string }) => (
    <button data-testid={`ai-estimate-${listingId}`}>AI Estimate</button>
  ),
}));

// Mock AiAdviceCards (pulls in @tanstack/react-query which needs a provider)
vi.mock('@/components/listings/ai-advice-cards', () => ({
  AiAdviceCards: ({ listingId }: { listingId: string }) => (
    <button data-testid={`ai-advice-${listingId}`}>AI Advice</button>
  ),
}));

// Mock InquiryModal
vi.mock('@/components/listings/inquiry-modal', () => ({
  InquiryModal: () => null,
}));

// Mock analytics API (used for nearby POIs fetch + AI advice)
vi.mock('@/lib/analytics-api', () => ({
  analyticsApi: {
    getNearbyPOIs: vi.fn().mockResolvedValue({ pois: [], center: { lat: 0, lng: 0 } }),
    getListingAiAdvice: vi.fn().mockResolvedValue({
      valuation: {
        estimateVND: 3_500_000_000,
        lowVND: 3_000_000_000,
        highVND: 4_000_000_000,
        confidence: 'medium',
        rationale: 'Giá hợp lý cho khu vực',
      },
      advice: {
        summary: 'Tổng quan AI',
        pros: ['Vị trí đẹp'],
        cons: ['Giá cao hơn trung bình'],
        suitableFor: ['Gia đình trẻ'],
      },
      model: 'claude-opus-4-5',
      cacheHit: false,
    }),
  },
}));

// Mock listings API (used for neighborhood score + price history + similar)
vi.mock('@/lib/listings-api', async () => {
  const actual = await vi.importActual<typeof import('@/lib/listings-api')>('@/lib/listings-api');
  return {
    ...actual,
    listingsApi: {
      getNeighborhoodScore: vi.fn().mockResolvedValue(null),
      getPriceHistory: vi.fn().mockResolvedValue([]),
      getSimilar: vi.fn().mockResolvedValue([]),
    },
  };
});

// Mock currency
vi.mock('@/lib/currency', () => ({
  formatPrice: (price: string) => {
    const n = Number(price);
    if (n >= 1_000_000_000) return `${(n / 1_000_000_000).toFixed(1)} tỷ`;
    return n.toLocaleString('vi-VN');
  },
  formatPricePerM2: (price: number) => `${(price / 1_000_000).toFixed(1)} tr/m²`,
}));

function makeListing(overrides: Partial<ListingDetail> = {}): ListingDetail {
  return {
    id: 'listing-1',
    status: 'ACTIVE',
    transactionType: 'SALE',
    priceVND: '3500000000',
    pricePerM2: 40_000_000,
    rentPriceMonthly: null,
    commissionPct: null,
    viewCount: 100,
    saveCount: 10,
    inquiryCount: 5,
    publishedAt: '2026-01-01T00:00:00Z',
    createdAt: '2025-12-01T00:00:00Z',
    valuationEstimate: null,
    agentQualityScore: null,
    similarCount: 3,
    property: {
      id: 'prop-1',
      propertyType: 'APARTMENT',
      title: 'Căn hộ 2PN Vinhomes Central Park',
      description: 'Căn hộ đẹp view sông Sài Gòn',
      address: '208 Nguyễn Hữu Cảnh',
      ward: 'Phường 22',
      district: 'Quận Bình Thạnh',
      city: 'Hồ Chí Minh',
      areaM2: 75,
      usableAreaM2: 68,
      bedrooms: 2,
      bathrooms: 2,
      floors: null,
      floor: null,
      totalFloors: null,
      direction: 'SOUTH',
      yearBuilt: 2020,
      legalStatus: 'Sổ hồng',
      amenities: ['Hồ bơi', 'Gym'],
      nearbyPOIs: null,
      metroDistanceM: null,
      projectName: 'Vinhomes Central Park',
      latitude: 10.7975,
      longitude: 106.721,
      furnishing: null,
      propertyCondition: null,
      balconyDirection: null,
      maintenanceFeeVND: null,
      parkingSlots: null,
      viewType: [],
      petFriendly: null,
      suitableFor: [],
      whyThisLocation: null,
      media: [
        { id: 'media-1', type: 'image', url: 'https://example.com/img1.jpg', order: 0, caption: null },
      ],
    },
    seller: {
      id: 'seller-1',
      fullName: 'Nguyen Van B',
      phone: '0912345678',
    },
    agent: null,
    ...overrides,
  };
}

describe('ListingDetailClient', () => {
  it('renders property title', () => {
    render(<ListingDetailClient listing={makeListing()} />);
    expect(screen.getByRole('heading', { level: 1 })).toHaveTextContent('Căn hộ 2PN Vinhomes Central Park');
  });

  it('renders formatted price', () => {
    render(<ListingDetailClient listing={makeListing()} />);
    // price appears in the contact sidebar as "3.5 tỷ VND"
    const all = document.body.textContent ?? '';
    expect(all).toMatch(/3[\s\S]*tỷ|3\.500\.000\.000/);
  });

  it('renders property address', () => {
    render(<ListingDetailClient listing={makeListing()} />);
    expect(screen.getByText(/208 Nguyễn Hữu Cảnh/)).toBeInTheDocument();
  });

  it('renders transaction type badge', () => {
    render(<ListingDetailClient listing={makeListing()} />);
    expect(screen.getByText('Bán')).toBeInTheDocument();
  });

  it('renders property type badge', () => {
    render(<ListingDetailClient listing={makeListing()} />);
    // "Căn hộ" appears in badge, title, description, and detail row — use getAllByText
    const matches = screen.getAllByText(/Căn hộ/);
    expect(matches.length).toBeGreaterThanOrEqual(1);
  });

  it('renders area in quick stats', () => {
    render(<ListingDetailClient listing={makeListing()} />);
    // "75 m²" may appear in multiple places (quick stats and detail row)
    const matches = screen.getAllByText(/75 m/);
    expect(matches.length).toBeGreaterThanOrEqual(1);
  });

  it('renders bedrooms in quick stats', () => {
    render(<ListingDetailClient listing={makeListing()} />);
    // Bedrooms value is displayed in the quick stats
    const allText = document.body.textContent;
    expect(allText).toContain('2');
  });

  it('renders description section', () => {
    render(<ListingDetailClient listing={makeListing()} />);
    expect(screen.getByText('Mô tả')).toBeInTheDocument();
    expect(screen.getByText('Căn hộ đẹp view sông Sài Gòn')).toBeInTheDocument();
  });

  it('renders seller contact info', () => {
    render(<ListingDetailClient listing={makeListing()} />);
    expect(screen.getByText('Nguyen Van B')).toBeInTheDocument();
    expect(screen.getByText('0912345678')).toBeInTheDocument();
  });

  it('renders Gọi ngay button', () => {
    render(<ListingDetailClient listing={makeListing()} />);
    expect(screen.getByText('Gọi ngay')).toBeInTheDocument();
  });

  it('renders view/save/inquiry stats', () => {
    render(<ListingDetailClient listing={makeListing()} />);
    expect(screen.getByText('100')).toBeInTheDocument(); // viewCount
    expect(screen.getByText('10')).toBeInTheDocument(); // saveCount
    expect(screen.getByText('5')).toBeInTheDocument(); // inquiryCount
  });

  it('renders amenities when present', () => {
    render(<ListingDetailClient listing={makeListing()} />);
    expect(screen.getByText('Hồ bơi')).toBeInTheDocument();
    expect(screen.getByText('Gym')).toBeInTheDocument();
  });

  it('does not render amenities section when empty', () => {
    const listing = makeListing();
    listing.property.amenities = [];
    render(<ListingDetailClient listing={listing} />);
    expect(screen.queryByText('Tiện ích')).not.toBeInTheDocument();
  });

  it('renders rent price when present', () => {
    render(<ListingDetailClient listing={makeListing({ rentPriceMonthly: '15000000' })} />);
    // Rent text contains monthly rent info
    const content = document.body.textContent ?? '';
    // Check for the rent amount - format may vary; at minimum the number should appear
    expect(content).toMatch(/15[.,]000[.,]000/);
  });

  it('renders breadcrumb navigation', () => {
    render(<ListingDetailClient listing={makeListing()} />);
    // Breadcrumb uses unicode chars
    const nav = screen.getByRole('navigation');
    expect(nav).toBeInTheDocument();
  });

  it('renders compare button', () => {
    render(<ListingDetailClient listing={makeListing()} />);
    const btns = screen.getAllByTestId('compare-btn-listing-1');
    expect(btns.length).toBeGreaterThanOrEqual(1);
  });

  it('renders AI estimate button', () => {
    render(<ListingDetailClient listing={makeListing()} />);
    expect(screen.getByTestId('ai-estimate-listing-1')).toBeInTheDocument();
  });

  it('renders agent commission info when present', () => {
    const listing = makeListing({
      agent: { agency: 'Công ty ABC', id: 'agent-1' } as ListingDetail['agent'],
      commissionPct: 2.5,
    });
    render(<ListingDetailClient listing={listing} />);
    expect(screen.getByText('Công ty ABC')).toBeInTheDocument();
    expect(screen.getByText('Hoa hồng: 2.5%')).toBeInTheDocument();
  });

  it('renders published date', () => {
    render(<ListingDetailClient listing={makeListing()} />);
    expect(screen.getByText(/Đăng ngày/)).toBeInTheDocument();
  });
});
