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

vi.mock('@inertiajs/react', async () => {
  const actual = await vi.importActual('@inertiajs/react');
  return {
    ...actual,
    Link: ({ children, href }: { children: React.ReactNode; href: string }) => (
      <a href={href}>{children}</a>
    ),
  };
});

import ClusterCard from '@/Components/TopicClusters/ClusterCard';

function makeCluster(overrides: Record<string, unknown> = {}) {
  return {
    id: 1,
    name: 'Running Shoes',
    total_demand: 5000,
    coverage_percentage: 65.5,
    hub_page_url: 'https://example.com/running-shoes',
    metadata: {
      representative_queries: [
        'best running shoes',
        'running shoes for beginners',
        'affordable running shoes',
      ],
    },
    page_count: 8,
    query_count: 25,
    gap_count: 3,
    ...overrides,
  };
}

beforeEach(() => {
  vi.stubGlobal(
    'route',
    vi.fn(() => '/mock-route'),
  );
});

describe('ClusterCard', () => {
  it('renders cluster name', () => {
    render(<ClusterCard cluster={makeCluster()} siteId={1} />);
    expect(screen.getByText('Running Shoes')).toBeInTheDocument();
  });

  it('renders coverage percentage with correct badge variant', () => {
    const { rerender } = render(
      <ClusterCard cluster={makeCluster({ coverage_percentage: 75 })} siteId={1} />,
    );
    expect(screen.getByText('75% Coverage')).toBeInTheDocument();

    rerender(<ClusterCard cluster={makeCluster({ coverage_percentage: 50 })} siteId={1} />);
    expect(screen.getByText('50% Coverage')).toBeInTheDocument();

    rerender(<ClusterCard cluster={makeCluster({ coverage_percentage: 25 })} siteId={1} />);
    expect(screen.getByText('25% Coverage')).toBeInTheDocument();
  });

  it('renders total demand with proper formatting', () => {
    render(<ClusterCard cluster={makeCluster({ total_demand: 12345 })} siteId={1} />);
    expect(screen.getByText('12,345')).toBeInTheDocument();
    expect(screen.getByText('demand')).toBeInTheDocument();
  });

  it('renders page count with singular form', () => {
    render(<ClusterCard cluster={makeCluster({ page_count: 1 })} siteId={1} />);
    expect(screen.getByText('1')).toBeInTheDocument();
    expect(screen.getByText('page')).toBeInTheDocument();
  });

  it('renders page count with plural form', () => {
    render(<ClusterCard cluster={makeCluster({ page_count: 8 })} siteId={1} />);
    expect(screen.getByText('8')).toBeInTheDocument();
    expect(screen.getByText('pages')).toBeInTheDocument();
  });

  it('renders gap count', () => {
    render(<ClusterCard cluster={makeCluster({ gap_count: 5 })} siteId={1} />);
    expect(screen.getByText('5')).toBeInTheDocument();
    expect(screen.getByText('Gaps')).toBeInTheDocument();
  });

  it('renders top representative queries', () => {
    render(<ClusterCard cluster={makeCluster()} siteId={1} />);
    expect(screen.getByText('Top queries:')).toBeInTheDocument();
    expect(
      screen.getByText('best running shoes, running shoes for beginners, affordable running shoes'),
    ).toBeInTheDocument();
  });

  it('limits queries to top 3', () => {
    const cluster = makeCluster({
      metadata: {
        representative_queries: ['query 1', 'query 2', 'query 3', 'query 4', 'query 5'],
      },
    });
    render(<ClusterCard cluster={cluster} siteId={1} />);
    const queriesText = screen.getByText(/query 1, query 2, query 3/);
    expect(queriesText).toBeInTheDocument();
    expect(queriesText.textContent).not.toContain('query 4');
  });

  it('does not render queries section when no queries', () => {
    const cluster = makeCluster({
      metadata: {},
    });
    render(<ClusterCard cluster={cluster} siteId={1} />);
    expect(screen.queryByText('Top queries:')).not.toBeInTheDocument();
  });

  it('renders hub page URL when expanded', async () => {
    const user = userEvent.setup();
    render(<ClusterCard cluster={makeCluster()} siteId={1} />);

    const hubButton = screen.getByText('Hub page');
    await user.click(hubButton);

    const link = screen.getByRole('link', { name: /https:\/\/example\.com\/running-shoes/i });
    expect(link).toBeInTheDocument();
    expect(link).toHaveAttribute('href', 'https://example.com/running-shoes');
    expect(link).toHaveAttribute('target', '_blank');
    expect(link).toHaveAttribute('rel', 'noopener noreferrer');
  });

  it('does not render hub page button when no hub page URL', () => {
    const cluster = makeCluster({ hub_page_url: null });
    render(<ClusterCard cluster={cluster} siteId={1} />);
    expect(screen.queryByText('Hub page')).not.toBeInTheDocument();
  });

  it('renders View Details button with correct link', () => {
    render(<ClusterCard cluster={makeCluster()} siteId={42} />);
    const button = screen.getByRole('link', { name: 'View Details' });
    expect(button).toBeInTheDocument();
  });

  it('toggles hub page section on click', async () => {
    const user = userEvent.setup();
    const { container } = render(<ClusterCard cluster={makeCluster()} siteId={1} />);

    const hubButton = screen.getByText('Hub page');

    // Initially hidden (grid-rows-[0fr])
    const collapsibleContainer = container.querySelector('.grid');
    expect(collapsibleContainer).toHaveClass('grid-rows-[0fr]');
    expect(collapsibleContainer).toHaveClass('opacity-0');

    // Click to expand
    await user.click(hubButton);
    expect(collapsibleContainer).toHaveClass('grid-rows-[1fr]');
    expect(collapsibleContainer).toHaveClass('opacity-100');

    // Click to collapse
    await user.click(hubButton);
    expect(collapsibleContainer).toHaveClass('grid-rows-[0fr]');
    expect(collapsibleContainer).toHaveClass('opacity-0');
  });

  it('handles empty metadata gracefully', () => {
    const cluster = makeCluster({
      metadata: {},
    });
    render(<ClusterCard cluster={cluster} siteId={1} />);
    expect(screen.getByText('Running Shoes')).toBeInTheDocument();
  });

  it('rounds coverage percentage to whole number', () => {
    render(<ClusterCard cluster={makeCluster({ coverage_percentage: 65.789 })} siteId={1} />);
    expect(screen.getByText('66% Coverage')).toBeInTheDocument();
  });
});
