import { render, screen } from '@testing-library/react';
import { 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 RecommendationFunnel from './RecommendationFunnel';

describe('RecommendationFunnel', () => {
  it('renders card with title and description', () => {
    render(
      <RecommendationFunnel
        metrics={{
          generated: 100,
          approved: 50,
          applied: 25,
        }}
      />,
    );

    expect(screen.getByText('Recommendation Funnel')).toBeInTheDocument();
    expect(
      screen.getByText(/Track recommendations from generation to implementation/),
    ).toBeInTheDocument();
  });

  it('displays all three funnel stages with correct counts', () => {
    render(
      <RecommendationFunnel
        metrics={{
          generated: 100,
          approved: 50,
          applied: 25,
        }}
      />,
    );

    expect(screen.getByText('Generated')).toBeInTheDocument();
    expect(screen.getByText('Approved')).toBeInTheDocument();
    expect(screen.getByText('Applied')).toBeInTheDocument();

    // CountUp components will render the numbers
    expect(screen.getByText('100')).toBeInTheDocument();
    expect(screen.getByText('50')).toBeInTheDocument();
    expect(screen.getByText('25')).toBeInTheDocument();
  });

  it('calculates and displays percentages correctly', () => {
    render(
      <RecommendationFunnel
        metrics={{
          generated: 100,
          approved: 50,
          applied: 25,
        }}
      />,
    );

    // Percentage text is split: CountUp renders the number, then "% of total" follows
    // Use regex to match the container text
    expect(screen.getAllByText(/of total/)).toHaveLength(3);
    expect(screen.getByText(/50\.0% of total/)).toBeInTheDocument();
    expect(screen.getByText(/25\.0% of total/)).toBeInTheDocument();
  });

  it('handles zero generated recommendations with empty state', () => {
    render(
      <RecommendationFunnel
        metrics={{
          generated: 0,
          approved: 0,
          applied: 0,
        }}
      />,
    );

    expect(screen.getByText(/No recommendations yet/)).toBeInTheDocument();
    expect(
      screen.getByText(/Run an analysis first to generate recommendations/),
    ).toBeInTheDocument();

    // Should not show funnel stages
    expect(screen.queryByText('Generated')).not.toBeInTheDocument();
    expect(screen.queryByText('Approved')).not.toBeInTheDocument();
    expect(screen.queryByText('Applied')).not.toBeInTheDocument();
  });

  it('handles partial funnel progression', () => {
    render(
      <RecommendationFunnel
        metrics={{
          generated: 100,
          approved: 30,
          applied: 0,
        }}
      />,
    );

    expect(screen.getByText('100')).toBeInTheDocument();
    expect(screen.getByText('30')).toBeInTheDocument();
    expect(screen.getByText('0')).toBeInTheDocument();

    // Check "of total" appears 3 times (one per stage)
    expect(screen.getAllByText(/of total/)).toHaveLength(3);
    expect(screen.getByText(/30\.0% of total/)).toBeInTheDocument();
    // Applied = 0% — use getByText with function to avoid matching "100.0%"
    const zeroEl = screen.getByText((content) => content === '0.0% of total');
    expect(zeroEl).toBeInTheDocument();
  });

  it('handles 100% conversion rate', () => {
    render(
      <RecommendationFunnel
        metrics={{
          generated: 50,
          approved: 50,
          applied: 50,
        }}
      />,
    );

    // All stages should show "of total" text
    const ofTotals = screen.getAllByText(/of total/);
    expect(ofTotals).toHaveLength(3);
  });

  it('calculates percentages correctly for odd numbers', () => {
    render(
      <RecommendationFunnel
        metrics={{
          generated: 77,
          approved: 33,
          applied: 11,
        }}
      />,
    );

    // 33/77 = 42.857... %
    expect(screen.getByText(/42\.9% of total/)).toBeInTheDocument();
    // 11/77 = 14.285... %
    expect(screen.getByText(/14\.3% of total/)).toBeInTheDocument();
  });

  it('handles single digit counts', () => {
    render(
      <RecommendationFunnel
        metrics={{
          generated: 5,
          approved: 3,
          applied: 1,
        }}
      />,
    );

    expect(screen.getByText('5')).toBeInTheDocument();
    expect(screen.getByText('3')).toBeInTheDocument();
    expect(screen.getByText('1')).toBeInTheDocument();

    // 3/5 = 60%
    expect(screen.getByText(/60\.0% of total/)).toBeInTheDocument();
    // 1/5 = 20%
    expect(screen.getByText(/20\.0% of total/)).toBeInTheDocument();
  });

  it('handles large numbers', () => {
    render(
      <RecommendationFunnel
        metrics={{
          generated: 10000,
          approved: 5000,
          applied: 2500,
        }}
      />,
    );

    // CountUp component should handle large numbers
    expect(screen.getByText('10,000')).toBeInTheDocument();
    expect(screen.getByText('5,000')).toBeInTheDocument();
    expect(screen.getByText('2,500')).toBeInTheDocument();
  });

  it('shows conversion rates between stages', () => {
    render(
      <RecommendationFunnel
        metrics={{
          generated: 100,
          approved: 50,
          applied: 25,
        }}
      />,
    );

    // Conversion rates should appear as "X% conversion"
    expect(screen.getAllByText(/conversion/)).toHaveLength(2);
  });

  it('shows clickable link description when siteId is provided', () => {
    render(
      <RecommendationFunnel metrics={{ generated: 10, approved: 5, applied: 2 }} siteId={1} />,
    );

    expect(screen.getByText(/click a stage to filter/)).toBeInTheDocument();
  });

  it('does not show click description when no siteId', () => {
    render(<RecommendationFunnel metrics={{ generated: 10, approved: 5, applied: 2 }} />);

    expect(screen.queryByText(/click a stage to filter/)).not.toBeInTheDocument();
  });
});
