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

vi.mock('@/Components/Shared/MetricDelta', () => ({
  default: ({ value, format }: { value: number; format: string }) => (
    <span data-testid="metric-delta" data-value={value} data-format={format}>
      {value}%
    </span>
  ),
}));
vi.mock('@/Components/Recommendations/GenerateDraftButton', () => ({
  default: () => <button data-testid="generate-draft-btn">Generate</button>,
}));
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 RecommendationCard from '@/Components/Recommendations/RecommendationCard';

function makeRecommendation(overrides: Record<string, unknown> = {}) {
  return {
    id: 1,
    page_url: '/test-page',
    action_type: 'content_rewrite',
    impact_score: 75,
    confidence_score: 0.8,
    title: 'Improve page content',
    reasoning: 'This page has declining traffic',
    evidence: {
      clicks_before: 1200,
      clicks_after: 800,
      delta_percent: -33.3,
      position_before: 5.2,
      position_after: 8.1,
    },
    has_draft: false,
    latest_draft_id: null,
    lifecycle_status: 'pending',
    ...overrides,
  };
}

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

describe('RecommendationCard', () => {
  it('renders clicks before and after values', async () => {
    const user = userEvent.setup();
    render(
      <RecommendationCard recommendation={makeRecommendation()} siteId={1} aiAvailable={true} />,
    );

    await user.click(screen.getByText('View evidence'));

    expect(screen.getByText((1200).toLocaleString())).toBeInTheDocument();
    expect(screen.getByText((800).toLocaleString())).toBeInTheDocument();
  });

  it('renders MetricDelta with correct delta_percent', async () => {
    const user = userEvent.setup();
    render(
      <RecommendationCard recommendation={makeRecommendation()} siteId={1} aiAvailable={true} />,
    );

    await user.click(screen.getByText('View evidence'));

    const metricDelta = screen.getByTestId('metric-delta');
    expect(metricDelta).toHaveAttribute('data-value', '-33.3');
    expect(metricDelta).toHaveAttribute('data-format', 'percent');
  });

  it('renders position change when position data exists', async () => {
    const user = userEvent.setup();
    render(
      <RecommendationCard
        recommendation={makeRecommendation({
          evidence: {
            clicks_before: 1200,
            clicks_after: 800,
            delta_percent: -33.3,
            position_before: 5.2,
            position_after: 8.1,
          },
        })}
        siteId={1}
        aiAvailable={true}
      />,
    );

    await user.click(screen.getByText('View evidence'));

    expect(screen.getByText('Position')).toBeInTheDocument();
    // Position values are rendered inside the same span with an arrow between them
    const positionSpan = screen.getByText((_content, element) => {
      return (
        element?.tagName === 'SPAN' &&
        element.classList.contains('tabular-nums') &&
        element.textContent?.includes('5.2') === true &&
        element.textContent?.includes('8.1') === true
      );
    });
    expect(positionSpan).toBeInTheDocument();
  });

  it('does not render position section when position_before is undefined', async () => {
    const user = userEvent.setup();
    render(
      <RecommendationCard
        recommendation={makeRecommendation({
          evidence: {
            clicks_before: 1200,
            clicks_after: 800,
            delta_percent: -33.3,
          },
        })}
        siteId={1}
        aiAvailable={true}
      />,
    );

    await user.click(screen.getByText('View evidence'));

    expect(screen.queryByText('Position')).not.toBeInTheDocument();
  });

  it('bar widths are proportional to clicks values', async () => {
    const user = userEvent.setup();
    const { container } = render(
      <RecommendationCard
        recommendation={makeRecommendation({
          evidence: {
            clicks_before: 1000,
            clicks_after: 500,
            delta_percent: -50,
          },
        })}
        siteId={1}
        aiAvailable={true}
      />,
    );

    await user.click(screen.getByText('View evidence'));

    // clicks_before = 1000, clicks_after = 500
    // barWidth(1000, 500) = round((1000 / 1000) * 100) = 100
    // barWidth(500, 1000) = round((500 / 1000) * 100) = 50
    const bars = container.querySelectorAll<HTMLDivElement>('.rounded-sm');
    expect(bars[0].style.width).toBe('100%');
    expect(bars[1].style.width).toBe('50%');
  });

  describe('page URL display (Phase 4.2)', () => {
    it('renders page_url as an external link below the title', () => {
      render(
        <RecommendationCard
          recommendation={makeRecommendation({ page_url: 'https://example.com/some-page' })}
          siteId={1}
          aiAvailable={true}
        />,
      );

      const link = screen.getByRole('link', { name: /\/some-page/i });
      expect(link).toHaveAttribute('href', 'https://example.com/some-page');
      expect(link).toHaveAttribute('target', '_blank');
      expect(link).toHaveAttribute('rel', 'noopener noreferrer');
      expect(link).toHaveAttribute('title', 'Opens in a new window');
    });

    it('truncates long page URLs in the display text', () => {
      const longUrl = 'https://example.com/' + 'x'.repeat(100);
      render(
        <RecommendationCard
          recommendation={makeRecommendation({ page_url: longUrl })}
          siteId={1}
          aiAvailable={true}
        />,
      );

      const link = screen.getByTitle('Opens in a new window');
      expect(link.textContent).toContain('…');
      expect(link).toHaveAttribute('href', longUrl);
    });

    it('renders ExternalLink icon inside the page URL anchor', () => {
      render(
        <RecommendationCard
          recommendation={makeRecommendation({ page_url: 'https://example.com/page' })}
          siteId={1}
          aiAvailable={true}
        />,
      );

      const link = screen.getByTitle('Opens in a new window');
      const icon = link.querySelector('svg');
      expect(icon).toBeInTheDocument();
    });
  });

  describe('impact score typography (Phase 7.1)', () => {
    it('renders impact score with text-xl font-semibold classes', () => {
      const { container } = render(
        <RecommendationCard
          recommendation={makeRecommendation({ impact_score: 85 })}
          siteId={1}
          aiAvailable={true}
        />,
      );

      const impactEl = container.querySelector('.text-xl.font-semibold');
      expect(impactEl).not.toBeNull();
      expect(impactEl?.textContent).toBe('85');
    });

    it('does not use text-2xl font-bold for impact score', () => {
      const { container } = render(
        <RecommendationCard
          recommendation={makeRecommendation({ impact_score: 85 })}
          siteId={1}
          aiAvailable={true}
        />,
      );

      const boldEl = container.querySelector('.text-2xl.font-bold');
      expect(boldEl).toBeNull();
    });
  });

  describe('evidence toggle aria-controls (Phase 7.2)', () => {
    it('toggle button has aria-controls pointing to evidence div id', () => {
      render(
        <RecommendationCard recommendation={makeRecommendation()} siteId={1} aiAvailable={true} />,
      );

      const toggle = screen.getByRole('button', { name: /view evidence/i });
      expect(toggle).toHaveAttribute('aria-controls', 'evidence-1');
    });

    it('evidence div has the correct id', () => {
      const { container } = render(
        <RecommendationCard
          recommendation={makeRecommendation({ id: 42 })}
          siteId={1}
          aiAvailable={true}
        />,
      );

      const evidenceDiv = container.querySelector('#evidence-42');
      expect(evidenceDiv).not.toBeNull();
    });

    it('aria-controls matches evidence div id for any recommendation id', () => {
      const { container } = render(
        <RecommendationCard
          recommendation={makeRecommendation({ id: 99 })}
          siteId={1}
          aiAvailable={true}
        />,
      );

      const toggle = screen.getByRole('button', { name: /view evidence/i });
      const ariaControlsId = toggle.getAttribute('aria-controls');
      const evidenceDiv = container.querySelector(`#${ariaControlsId}`);

      expect(ariaControlsId).toBe('evidence-99');
      expect(evidenceDiv).not.toBeNull();
    });
  });

  describe('ROI performance badge', () => {
    it('shows boosted badge when roi_performance_multiplier > 1.1', () => {
      render(
        <RecommendationCard
          recommendation={makeRecommendation({
            roi_performance_multiplier: 1.3,
            lifecycle_status: 'pending',
          })}
          siteId={1}
          aiAvailable={true}
        />,
      );
      expect(screen.getByText('↑ Boosted')).toBeInTheDocument();
    });

    it('shows suppressed badge when roi_performance_multiplier < 0.9', () => {
      render(
        <RecommendationCard
          recommendation={makeRecommendation({
            roi_performance_multiplier: 0.7,
            lifecycle_status: 'pending',
          })}
          siteId={1}
          aiAvailable={true}
        />,
      );
      expect(screen.getByText('↓ Suppressed')).toBeInTheDocument();
    });

    it('does not show ROI badge when multiplier is null', () => {
      render(
        <RecommendationCard
          recommendation={makeRecommendation({
            roi_performance_multiplier: null,
            lifecycle_status: 'pending',
          })}
          siteId={1}
          aiAvailable={true}
        />,
      );
      expect(screen.queryByText('↑ Boosted')).not.toBeInTheDocument();
      expect(screen.queryByText('↓ Suppressed')).not.toBeInTheDocument();
    });

    it('does not show ROI badge when multiplier is between 0.9 and 1.1 exclusive', () => {
      render(
        <RecommendationCard
          recommendation={makeRecommendation({
            roi_performance_multiplier: 1.0,
            lifecycle_status: 'pending',
          })}
          siteId={1}
          aiAvailable={true}
        />,
      );
      expect(screen.queryByText('↑ Boosted')).not.toBeInTheDocument();
      expect(screen.queryByText('↓ Suppressed')).not.toBeInTheDocument();
    });

    it('shows boosted badge at exactly the 1.1 boundary (inclusive)', () => {
      render(
        <RecommendationCard
          recommendation={makeRecommendation({
            roi_performance_multiplier: 1.1,
            lifecycle_status: 'pending',
          })}
          siteId={1}
          aiAvailable={true}
        />,
      );
      expect(screen.getByText('↑ Boosted')).toBeInTheDocument();
    });

    it('shows suppressed badge at exactly the 0.9 boundary (inclusive)', () => {
      render(
        <RecommendationCard
          recommendation={makeRecommendation({
            roi_performance_multiplier: 0.9,
            lifecycle_status: 'pending',
          })}
          siteId={1}
          aiAvailable={true}
        />,
      );
      expect(screen.getByText('↓ Suppressed')).toBeInTheDocument();
    });
  });

  describe('analysisRunId prop (Phase 4.2)', () => {
    it('shows "View in analysis" link when analysisRunId is provided', () => {
      render(
        <RecommendationCard
          recommendation={makeRecommendation()}
          siteId={1}
          aiAvailable={true}
          analysisRunId={5}
        />,
      );

      expect(screen.getByRole('link', { name: /view in analysis/i })).toBeInTheDocument();
    });

    it('does not show "View in analysis" link when analysisRunId is not provided', () => {
      render(
        <RecommendationCard recommendation={makeRecommendation()} siteId={1} aiAvailable={true} />,
      );

      expect(screen.queryByRole('link', { name: /view in analysis/i })).not.toBeInTheDocument();
    });
  });
});
