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

import OpportunityMapIndex from './Index';

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(),
      reload: vi.fn(),
      on: vi.fn(() => vi.fn()),
    },
    usePage: () => ({
      props: {},
    }),
  };
});

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/OpportunityMap/OpportunityFilters', () => ({
  default: () => <div data-testid="opportunity-filters" />,
}));

vi.mock('@/Components/OpportunityMap/UnifiedCard', () => ({
  default: ({ opportunity }: { opportunity: { issue: string } }) => (
    <div data-testid="unified-card">{opportunity.issue}</div>
  ),
}));

vi.mock('@/Components/ui/empty-state', () => ({
  EmptyState: ({ title, description }: { title: string; description: string }) => (
    <div data-testid="empty-state">
      <h2>{title}</h2>
      <p>{description}</p>
    </div>
  ),
}));

describe('OpportunityMapIndex', () => {
  const mockSite = {
    id: 1,
    name: 'Test Site',
    domain: 'example.com',
  };

  const mockOpportunity = {
    opportunity_type: 'recommendation' as const,
    opportunity_id: 1,
    page_url: 'https://example.com/page',
    demand: {
      clicks_before: 100,
      clicks_after: 50,
      delta_percent: -50,
    },
    issue: 'Traffic decline detected',
    action: 'content_rewrite',
    confidence: 85,
    impact_score: 90,
    reasoning: 'Page has lost significant traffic',
  };

  const mockFilters = {
    type: null,
    sort: null,
    min_confidence: null,
    min_impact: null,
  };

  const mockCounts = {
    total: 0,
    recommendation: 0,
    freshness: 0,
    cannibalization: 0,
    topic_gap: 0,
  };

  beforeEach(() => {
    vi.clearAllMocks();
  });

  function paginated<T>(data: T[]) {
    return {
      data,
      current_page: 1,
      last_page: 1,
      per_page: 20,
      total: data.length,
      from: data.length ? 1 : null,
      to: data.length ? data.length : null,
      links: [] as { url: string | null; label: string; active: boolean }[],
      next_page_url: null,
      prev_page_url: null,
    };
  }

  it('renders page title and description', () => {
    render(
      <OpportunityMapIndex
        site={mockSite}
        opportunities={paginated([])}
        filters={mockFilters}
        counts={mockCounts}
      />,
    );

    expect(screen.getByText('Opportunity Map')).toBeInTheDocument();
    expect(screen.getByText('All opportunities in one unified view')).toBeInTheDocument();
  });

  it('renders empty state when no opportunities exist', () => {
    render(
      <OpportunityMapIndex
        site={mockSite}
        opportunities={paginated([])}
        filters={mockFilters}
        counts={mockCounts}
      />,
    );

    expect(screen.getByText('No opportunities discovered yet')).toBeInTheDocument();
    expect(
      screen.getByText(/run at least one analysis to populate this view/i),
    ).toBeInTheDocument();
  });

  it('renders SiteNav component', () => {
    render(
      <OpportunityMapIndex
        site={mockSite}
        opportunities={paginated([])}
        filters={mockFilters}
        counts={mockCounts}
      />,
    );

    expect(screen.getByTestId('site-nav')).toBeInTheDocument();
  });

  it('renders Settings button with correct link', () => {
    render(
      <OpportunityMapIndex
        site={mockSite}
        opportunities={paginated([mockOpportunity])}
        filters={mockFilters}
        counts={{ ...mockCounts, total: 1, recommendation: 1 }}
      />,
    );

    const settingsLink = screen.getByRole('link', { name: /Settings/i });
    expect(settingsLink).toBeInTheDocument();
    expect(settingsLink).toHaveAttribute('href', '/sites/settings/analysis/show/1');
  });

  it('renders OpportunityFilters when opportunities exist', () => {
    render(
      <OpportunityMapIndex
        site={mockSite}
        opportunities={paginated([mockOpportunity])}
        filters={mockFilters}
        counts={{ ...mockCounts, total: 1, recommendation: 1 }}
      />,
    );

    expect(screen.getByTestId('opportunity-filters')).toBeInTheDocument();
  });

  it('renders UnifiedCard for each opportunity', () => {
    const opportunities = [
      mockOpportunity,
      { ...mockOpportunity, opportunity_id: 2, issue: 'Another issue' },
    ];

    render(
      <OpportunityMapIndex
        site={mockSite}
        opportunities={paginated(opportunities)}
        filters={mockFilters}
        counts={{ ...mockCounts, total: 2, recommendation: 2 }}
      />,
    );

    expect(screen.getByText('Traffic decline detected')).toBeInTheDocument();
    expect(screen.getByText('Another issue')).toBeInTheDocument();
    expect(screen.getAllByTestId('unified-card')).toHaveLength(2);
  });

  it('shows empty state when opportunities exist but filters match none', () => {
    render(
      <OpportunityMapIndex
        site={mockSite}
        opportunities={paginated([])}
        filters={{ ...mockFilters, type: 'recommendation' }}
        counts={{ ...mockCounts, total: 10 }}
      />,
    );

    // Filters are shown because total > 0
    expect(screen.getByTestId('opportunity-filters')).toBeInTheDocument();

    // But no opportunities match the filter
    expect(screen.getByText('No opportunities match your filters')).toBeInTheDocument();
  });

  it('renders correct page title in Head', () => {
    render(
      <OpportunityMapIndex
        site={mockSite}
        opportunities={paginated([])}
        filters={mockFilters}
        counts={mockCounts}
      />,
    );

    expect(document.title).toBe('Test Site - Opportunity Map');
  });

  it('updates local state when filter sliders change', () => {
    render(
      <OpportunityMapIndex
        site={mockSite}
        opportunities={paginated([mockOpportunity])}
        filters={mockFilters}
        counts={{ ...mockCounts, total: 1, recommendation: 1 }}
      />,
    );

    // Verify filters component is rendered with initial values
    expect(screen.getByTestId('opportunity-filters')).toBeInTheDocument();
  });

  it('clears selection when opportunities change', () => {
    const { rerender } = render(
      <OpportunityMapIndex
        site={mockSite}
        opportunities={paginated([mockOpportunity])}
        filters={mockFilters}
        counts={{ ...mockCounts, total: 1, recommendation: 1 }}
      />,
    );

    // Simulate selection (this would normally happen via checkbox click)
    // Re-render with new opportunities
    rerender(
      <OpportunityMapIndex
        site={mockSite}
        opportunities={paginated([{ ...mockOpportunity, opportunity_id: 999 }])}
        filters={mockFilters}
        counts={{ ...mockCounts, total: 1, recommendation: 1 }}
      />,
    );

    // Selection should be cleared (verified by no selection count shown)
    expect(screen.queryByText(/opportunities selected/)).not.toBeInTheDocument();
  });

  it('has DashboardLayout assigned', () => {
    // Verify the layout property is set
    expect(OpportunityMapIndex.layout).toBeDefined();
  });
});
