/* eslint-disable import-x/order */
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { render, screen, waitFor } from '@testing-library/react';
import * as React from 'react';
import { beforeEach, describe, expect, it, vi } from 'vitest';

// Mock next-intl with Vietnamese messages
const viMessages = await import('@/messages/vi.json');
vi.mock('next-intl', () => ({
  useTranslations: (namespace?: string) => {
    const messages = viMessages.default ?? viMessages;
    const ns = namespace
      ? (messages[namespace as keyof typeof messages] as Record<string, unknown> | undefined)
      : (messages as unknown as Record<string, unknown>);
    return (key: string, params?: Record<string, unknown>) => {
      if (!ns) return key;
      const parts = key.split('.');
      let val: unknown = ns;
      for (const p of parts) {
        val = (val as Record<string, unknown>)?.[p];
      }
      if (typeof val === 'string' && params) {
        return val.replace(/\{(\w+)\}/g, (_, k: string) => String(params[k] ?? `{${k}}`));
      }
      return typeof val === 'string' ? val : key;
    };
  },
  useLocale: () => 'vi',
  NextIntlClientProvider: ({ children }: { children: React.ReactNode }) => children,
}));

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

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

vi.mock('next/navigation', () => ({
  notFound: vi.fn(),
  useRouter: () => ({ push: vi.fn(), replace: vi.fn(), back: vi.fn() }),
  usePathname: () => '/',
  useSearchParams: () => new URLSearchParams(),
  redirect: vi.fn(),
}));

vi.mock('@/i18n/navigation', () => ({
  Link: ({ children, href, ...props }: { children: React.ReactNode; href: string; [key: string]: unknown }) => (
    <a href={href} {...props}>{children}</a>
  ),
  useRouter: () => ({ push: vi.fn(), replace: vi.fn() }),
  usePathname: () => '/',
  redirect: vi.fn(),
}));

vi.mock('@/lib/listings-api', () => ({
  listingsApi: {
    search: vi.fn().mockResolvedValue({ data: [], total: 42 }),
  },
}));

vi.mock('@/lib/hooks/use-analytics', () => ({
  useDistrictStats: () => ({
    data: {
      city: 'Ho Chi Minh',
      period: '2026-04',
      districts: [
        { district: 'Quan 1', avgPriceM2: 120000000, yoyChange: 2.4, totalListings: 150, daysOnMarket: 30 },
        { district: 'Quan 7', avgPriceM2: 65000000, yoyChange: -1.2, totalListings: 200, daysOnMarket: 25 },
      ],
    },
    isLoading: false,
  }),
  useHeatmap: () => ({
    data: { city: 'Ho Chi Minh', period: '2026-04', dataPoints: [] },
    isLoading: false,
  }),
  useMarketSnapshot: () => ({
    data: {
      city: 'Ho Chi Minh',
      activeCount: 1234,
      avgPrice: 5_000_000_000,
      medianPrice: 3_500_000_000,
      priceChangePct: { d1: 0.1, d7: 1.5, d30: 3.2 },
      avgPricePerM2: 85_000_000,
      daysOnMarket: 28,
      newListings24h: 15,
      cachedAt: null,
      nextRefreshAt: null,
    },
    isLoading: false,
  }),
  usePriceMovers: (direction: string) => ({
    data: {
      direction,
      period: '7d',
      level: 'district',
      limit: 5,
      movers: direction === 'up'
        ? [{ districtId: 'q1', name: 'Quận 1', currentAvgPrice: 10e9, previousAvgPrice: 9.5e9, changePct: 5.26, sampleSize: 20 }]
        : [{ districtId: 'q9', name: 'Quận 9', currentAvgPrice: 3e9, previousAvgPrice: 3.2e9, changePct: -6.25, sampleSize: 15 }],
    },
    isLoading: false,
  }),
  useTrendingAreas: () => ({
    data: {
      period: 7,
      level: 'district',
      limit: 10,
      areas: [
        { districtId: 'td', name: 'Thủ Đức', listings: 50, inquiries: 120, views: 3000, priceChangePct: 2.1, scoreRank: 1 },
      ],
    },
    isLoading: false,
  }),
}));

vi.mock('@/components/charts/district-heatmap', () => ({
  DistrictHeatmap: () => <div data-testid="heatmap">Heatmap</div>,
}));

vi.mock('@/components/charts/price-area-chart', () => ({
  PriceAreaChart: () => <div data-testid="price-chart">PriceChart</div>,
}));

import MarketDashboardPage from '../page';

function renderWithProviders(ui: React.ReactElement) {
  const queryClient = new QueryClient({
    defaultOptions: { queries: { retry: false } },
  });
  return render(
    <QueryClientProvider client={queryClient}>{ui}</QueryClientProvider>,
  );
}

describe('MarketDashboardPage', () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  it('renders KPI strip with market snapshot data', async () => {
    renderWithProviders(<MarketDashboardPage />);

    await waitFor(() => {
      expect(screen.getByText('GGI HCM')).toBeInTheDocument();
      expect(screen.getByText('Giá TB')).toBeInTheDocument();
      expect(screen.getByText('Giá trung vị')).toBeInTheDocument();
      expect(screen.getByText('Tin đang hoạt động')).toBeInTheDocument();
    });
  });

  it('renders top movers with district data', async () => {
    renderWithProviders(<MarketDashboardPage />);

    await waitFor(() => {
      // Quận 1 appears in both top movers and ticker; use getAllByText
      expect(screen.getAllByText('Quận 1').length).toBeGreaterThan(0);
      expect(screen.getAllByText('Quận 9').length).toBeGreaterThan(0);
    });
  });

  it('renders trending areas', async () => {
    renderWithProviders(<MarketDashboardPage />);

    await waitFor(() => {
      expect(screen.getByText('Thủ Đức')).toBeInTheDocument();
    });
  });

  it('renders district table with data', async () => {
    renderWithProviders(<MarketDashboardPage />);

    await waitFor(() => {
      expect(screen.getByText('Quan 1')).toBeInTheDocument();
      expect(screen.getByText('Quan 7')).toBeInTheDocument();
    });
  });

  it('renders price chart', async () => {
    renderWithProviders(<MarketDashboardPage />);

    await waitFor(() => {
      expect(screen.getByTestId('price-chart')).toBeInTheDocument();
    });
  });

  it('renders section headings', async () => {
    renderWithProviders(<MarketDashboardPage />);

    await waitFor(() => {
      expect(screen.getByText(/Top biến động giá/)).toBeInTheDocument();
      expect(screen.getByText(/Khu vực xu hướng/)).toBeInTheDocument();
      expect(screen.getByText('Tin đăng mới nhất')).toBeInTheDocument();
    });
  });
});
