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

import MetricsOverview from './MetricsOverview';

/**
 * The visible delta value is split across two text nodes inside the
 * `data-testid="metric-delta"` span ("+" / "-" then the formatted value), so a
 * text regex can match a non-element node. Locate the card by its title, walk up
 * to the card root, and read the delta span by test id — this is the element
 * carrying the semantic color class.
 */
function deltaSpanForCard(title: string): HTMLElement {
  const titleEl = screen.getByText(title);
  const card = titleEl.closest('.rounded-lg') as HTMLElement;
  return within(card).getByTestId('metric-delta');
}

function makeSummary(overrides: Record<string, number> = {}) {
  return {
    overall: {
      clicks_after: 1000,
      clicks_delta_pct: 25,
      impressions_after: 50000,
      impressions_delta_pct: 12,
      ctr_after: 0.05,
      ctr_delta_pct: 8,
      position_after: 4.2,
      position_delta_pct: 10,
      ...overrides,
    },
  };
}

describe('MetricsOverview', () => {
  it('renders nothing when overall summary is null', () => {
    const { container } = render(<MetricsOverview summary={{ overall: null }} />);
    expect(container.firstChild).toBeNull();
  });

  it('renders all four metric cards', () => {
    render(<MetricsOverview summary={makeSummary()} />);

    expect(screen.getByText('Clicks')).toBeInTheDocument();
    expect(screen.getByText('Impressions')).toBeInTheDocument();
    expect(screen.getByText('CTR')).toBeInTheDocument();
    expect(screen.getByText('Position')).toBeInTheDocument();
  });

  it('colors a RISE in Position as destructive/red (lower is better for position)', () => {
    render(<MetricsOverview summary={makeSummary({ position_delta_pct: 38.4 })} />);

    const positionDelta = deltaSpanForCard('Position');
    expect(positionDelta).toHaveTextContent('+38.4%');
    expect(positionDelta).toHaveClass('text-destructive');
    expect(positionDelta.className).not.toContain('text-success');
  });

  it('colors a DROP in Position as success/green (improving rank)', () => {
    render(<MetricsOverview summary={makeSummary({ position_delta_pct: -15 })} />);

    const positionDelta = deltaSpanForCard('Position');
    expect(positionDelta).toHaveTextContent('-15%');
    expect(positionDelta).toHaveClass('text-success');
    expect(positionDelta.className).not.toContain('text-destructive');
  });

  it('keeps Clicks higher-is-better: a drop (-53%) stays destructive/red', () => {
    render(<MetricsOverview summary={makeSummary({ clicks_delta_pct: -53 })} />);

    const clicksDelta = deltaSpanForCard('Clicks');
    expect(clicksDelta).toHaveTextContent('-53%');
    expect(clicksDelta).toHaveClass('text-destructive');
    expect(clicksDelta.className).not.toContain('text-success');
  });

  it('keeps Clicks higher-is-better: a rise (+25%) stays success/green', () => {
    render(<MetricsOverview summary={makeSummary({ clicks_delta_pct: 25 })} />);

    const clicksDelta = deltaSpanForCard('Clicks');
    expect(clicksDelta).toHaveTextContent('+25%');
    expect(clicksDelta).toHaveClass('text-success');
  });

  // AN-08: aria-labels and sr-only text describe impression-weighted framing (not per-day average)
  it('labels CTR as impression-weighted in aria-label and sr-only text', () => {
    render(<MetricsOverview summary={makeSummary()} />);

    // aria-label on the wrapper div (no "Average" prefix)
    expect(screen.getByRole('region', { name: 'Site performance metrics overview' })).toBeInTheDocument();
    expect(
      document.querySelector('[aria-label^="Click-through rate:"]'),
    ).toBeInTheDocument();
    // sr-only text should describe impression-weighted computation
    expect(screen.getByText(/impression-weighted click-through rate/i)).toBeInTheDocument();
  });

  it('labels Position as impression-weighted in aria-label and sr-only text', () => {
    render(<MetricsOverview summary={makeSummary()} />);

    expect(
      document.querySelector('[aria-label^="Position:"]'),
    ).toBeInTheDocument();
    expect(screen.getByText(/impression-weighted search result position/i)).toBeInTheDocument();
  });
});
