/**
 * TopDecliningPanel tests — DUX-02: per-row forward CTA.
 *
 * Verifies that every declining-page row exposes a working "Fix →" link
 * that deep-links to recommendations.index filtered by page_url.
 */
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, 'aria-label': ariaLabel }: { children: React.ReactNode; href: string; 'aria-label'?: string }) => (
      <a href={href} aria-label={ariaLabel}>{children}</a>
    ),
  };
});

import { TopDecliningPanel, type TopDecliningPage } from './TopDecliningPanel';

const FIRST_SITE = { id: '42', name: 'My Blog', domain: 'example.com' } as const;

const DECLINING_PAGES: TopDecliningPage[] = [
  { id: 1, page_url: 'https://example.com/blog/post-one', delta_percent: -32.5, delta_absolute: -120 },
  { id: 2, page_url: 'https://example.com/category/seo', delta_percent: -18.0, delta_absolute: -55 },
];

describe('TopDecliningPanel — DUX-02 per-row forward CTA', () => {
  it('renders a "Fix →" link for each declining page row', () => {
    render(
      <TopDecliningPanel
        topDeclining={DECLINING_PAGES}
        firstSite={FIRST_SITE}
        isDecliningLoading={false}
        hasLatestAnalysis
      />,
    );

    const fixLinks = screen.getAllByText('Fix →');
    expect(fixLinks).toHaveLength(DECLINING_PAGES.length);
  });

  it('Fix → links point to recommendations.index with page_url query param', () => {
    render(
      <TopDecliningPanel
        topDeclining={DECLINING_PAGES}
        firstSite={FIRST_SITE}
        isDecliningLoading={false}
        hasLatestAnalysis
      />,
    );

    const fixLinks = screen.getAllByRole('link', { name: /View recommendations for/ });
    expect(fixLinks).toHaveLength(DECLINING_PAGES.length);

    // First row — page_url must be encoded and appended
    expect(fixLinks[0]).toHaveAttribute(
      'href',
      `/sites/${FIRST_SITE.id}/recommendations?page_url=${encodeURIComponent(DECLINING_PAGES[0].page_url)}`,
    );
    // Second row
    expect(fixLinks[1]).toHaveAttribute(
      'href',
      `/sites/${FIRST_SITE.id}/recommendations?page_url=${encodeURIComponent(DECLINING_PAGES[1].page_url)}`,
    );
  });

  it('aria-label on each Fix → link names the target page_url', () => {
    render(
      <TopDecliningPanel
        topDeclining={DECLINING_PAGES}
        firstSite={FIRST_SITE}
        isDecliningLoading={false}
        hasLatestAnalysis
      />,
    );

    expect(
      screen.getByRole('link', {
        name: `View recommendations for ${DECLINING_PAGES[0].page_url}`,
      }),
    ).toBeInTheDocument();

    expect(
      screen.getByRole('link', {
        name: `View recommendations for ${DECLINING_PAGES[1].page_url}`,
      }),
    ).toBeInTheDocument();
  });

  it('omits Fix → CTA when firstSite is null', () => {
    render(
      <TopDecliningPanel
        topDeclining={DECLINING_PAGES}
        firstSite={null}
        isDecliningLoading={false}
        hasLatestAnalysis
      />,
    );

    expect(screen.queryAllByText('Fix →')).toHaveLength(0);
    // URL and delta should still render
    expect(screen.getAllByTitle(DECLINING_PAGES[0].page_url)).toHaveLength(1);
  });

  it('still renders the "View Full Analysis →" footer link alongside per-row CTAs', () => {
    render(
      <TopDecliningPanel
        topDeclining={DECLINING_PAGES}
        firstSite={FIRST_SITE}
        isDecliningLoading={false}
        hasLatestAnalysis
      />,
    );

    expect(screen.getByText('View Full Analysis →')).toBeInTheDocument();
    // Per-row CTAs are also present
    expect(screen.getAllByText('Fix →')).toHaveLength(DECLINING_PAGES.length);
  });

  it('renders delta percentages correctly alongside the CTA', () => {
    render(
      <TopDecliningPanel
        topDeclining={DECLINING_PAGES}
        firstSite={FIRST_SITE}
        isDecliningLoading={false}
        hasLatestAnalysis
      />,
    );

    // Negative deltas render without a leading + sign
    expect(screen.getByText('-32.5%')).toBeInTheDocument();
    expect(screen.getByText('-18.0%')).toBeInTheDocument();
  });

  it('renders loading skeletons (no Fix → links) when isDecliningLoading is true', () => {
    render(
      <TopDecliningPanel
        topDeclining={[]}
        firstSite={FIRST_SITE}
        isDecliningLoading
        hasLatestAnalysis={false}
      />,
    );

    // Loading state — no Fix → links
    expect(screen.queryAllByText('Fix →')).toHaveLength(0);
    // Accessible loading region present
    expect(screen.getByRole('status')).toBeInTheDocument();
  });

  it('shows the empty state (never-run) with a Run Analysis CTA when no data and no analysis', () => {
    render(
      <TopDecliningPanel
        topDeclining={[]}
        firstSite={FIRST_SITE}
        isDecliningLoading={false}
        hasLatestAnalysis={false}
      />,
    );

    expect(screen.queryAllByText('Fix →')).toHaveLength(0);
    expect(screen.getByText('Run Analysis')).toBeInTheDocument();
  });

  it('shows the empty state (ran-but-nothing) with View Recommendations CTA when analysis ran', () => {
    render(
      <TopDecliningPanel
        topDeclining={[]}
        firstSite={FIRST_SITE}
        isDecliningLoading={false}
        hasLatestAnalysis
      />,
    );

    expect(screen.queryAllByText('Fix →')).toHaveLength(0);
    expect(screen.getByText('View Recommendations')).toBeInTheDocument();
  });

  it('encodes special characters in page_url for the Fix → href (FND-002 regression lock)', () => {
    // page_url with ?, &, =, space — characters encodeURIComponent transforms.
    // Without encodeURIComponent these would break the query string.
    const specialPage: TopDecliningPage = {
      id: 99,
      page_url: 'https://example.com/p?a=1&b=2 c',
      delta_percent: -25.0,
      delta_absolute: -100,
    };

    render(
      <TopDecliningPanel
        topDeclining={[specialPage]}
        firstSite={FIRST_SITE}
        isDecliningLoading={false}
        hasLatestAnalysis
      />,
    );

    const link = screen.getByRole('link', {
      name: `View recommendations for ${specialPage.page_url}`,
    });
    // The page_url must be percent-encoded so it doesn't inject extra query params
    const href = link.getAttribute('href') ?? '';
    expect(href).toContain('%3F'); // ? encoded
    expect(href).toContain('%26'); // & encoded
    expect(href).toContain('%3D'); // = encoded
    // Also verify exactly one ? separates the route path from the query param
    expect(href.split('?')).toHaveLength(2);
  });
});
