import { render, screen } from '@testing-library/react';
import { describe, it, expect, vi, beforeEach } from 'vitest';

import { usePage } from '@inertiajs/react';

import Preview from './Preview';

const mockUsePolling = vi.fn();

vi.mock('@inertiajs/react', async () => {
  const actual = await vi.importActual('@inertiajs/react');
  return {
    ...actual,
    Head: ({ title }: { title: string }) => <title>{title}</title>,
    Link: ({ children, href }: { children: React.ReactNode; href: string }) => (
      <a href={href}>{children}</a>
    ),
    router: { visit: vi.fn(), post: vi.fn(), delete: vi.fn() },
    useForm: () => ({
      data: { expires_at: '', password: '' },
      setData: vi.fn(),
      post: vi.fn(),
      delete: vi.fn(),
      processing: false,
      reset: vi.fn(),
    }),
    usePage: vi.fn(() => ({
      props: {
        app_url: 'https://app.test',
        polling_interval_ms: 7500,
      },
    })),
  };
});

vi.mock('@/Layouts/DashboardLayout', () => ({
  default: ({ children }: { children: React.ReactNode }) => (
    <div data-testid="dashboard-layout">{children}</div>
  ),
}));

vi.mock('@/Components/Navigation/SiteNav', () => ({
  default: () => <div data-testid="site-nav" />,
}));

vi.mock('@/Components/Reports/ReportPreview', () => ({
  default: () => <div data-testid="report-preview" />,
}));

vi.mock('@/hooks/usePolling', () => ({
  usePolling: (...args: unknown[]) => mockUsePolling(...args),
}));

vi.mock('@/lib/format', () => ({
  formatNumber: (n: number) => String(n),
  formatDate: (d: string) => d,
}));

const mockSite = { id: 1, name: 'Test Site', domain: 'test.com' };

const makeMockReport = (status: string) => ({
  id: 42,
  name: 'Test Report',
  sections: ['traffic'],
  filters: {},
  status,
  generated_at: status === 'completed' ? '2026-04-10T10:00:00Z' : null,
  created_at: '2026-04-10T09:00:00Z',
  has_pdf: false,
  pdf_path: null,
  data: null,
});

describe('Reports/Preview', () => {
  beforeEach(() => {
    vi.clearAllMocks();
    vi.stubGlobal('route', vi.fn((name: string, params: unknown[]) => `/mock/${name}/${(params ?? []).join('/')}`));
  });

  it('passes polling_interval_ms from shared props to usePolling', () => {
    render(
      <Preview
        site={mockSite}
        report={makeMockReport('processing')}
        sharedLinks={[]}
      />,
    );

    expect(mockUsePolling).toHaveBeenCalledWith(
      true,
      7500,
      ['report'],
    );
  });

  it('polls when report status is pending', () => {
    render(
      <Preview
        site={mockSite}
        report={makeMockReport('pending')}
        sharedLinks={[]}
      />,
    );

    expect(mockUsePolling).toHaveBeenCalledWith(true, 7500, ['report']);
  });

  it('does not poll when report is completed', () => {
    render(
      <Preview
        site={mockSite}
        report={makeMockReport('completed')}
        sharedLinks={[]}
      />,
    );

    expect(mockUsePolling).toHaveBeenCalledWith(false, 7500, ['report']);
  });

  it('falls back to 3000ms interval when polling_interval_ms is absent from shared props', () => {
    vi.mocked(usePage).mockReturnValueOnce({
      props: { app_url: 'https://app.test' },
    } as unknown as ReturnType<typeof usePage>);

    render(
      <Preview
        site={mockSite}
        report={makeMockReport('processing')}
        sharedLinks={[]}
      />,
    );

    expect(mockUsePolling).toHaveBeenCalledWith(true, 3000, ['report']);
  });

  it('renders report name', () => {
    render(
      <Preview
        site={mockSite}
        report={makeMockReport('completed')}
        sharedLinks={[]}
      />,
    );

    expect(screen.getByText('Test Report')).toBeInTheDocument();
  });
});
