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

// Mock recharts to avoid canvas/SVG issues in jsdom
vi.mock('recharts', () => ({
  ResponsiveContainer: ({ children }: { children: React.ReactNode }) => (
    <div data-testid="responsive-container">{children}</div>
  ),
  LineChart: ({ children }: { children: React.ReactNode }) => (
    <div data-testid="line-chart">{children}</div>
  ),
  Line: () => <div data-testid="line" />,
  ReferenceLine: () => null,
  CartesianGrid: () => null,
  XAxis: () => null,
  YAxis: () => null,
  Tooltip: () => null,
  Legend: () => null,
}));

vi.mock('@/Components/theme', () => ({
  useTheme: () => ({ resolvedTheme: 'light' }),
}));

vi.mock('@/hooks/use-mobile', () => ({
  useIsMobile: () => false,
}));

import MetricTimeline from './MetricTimeline';

const baseMeta = {
  date_range: { from: '2026-01-01', to: '2026-03-31' },
  total_days: 90,
  totals: { clicks: 1200, impressions: 45000, avg_position: 12.4 },
};

const baseSeries = [
  { date: '2026-01-01', clicks: 100, impressions: 4000, position: 11.2 },
  { date: '2026-01-08', clicks: 120, impressions: 4500, position: 10.8 },
];

describe('MetricTimeline — F5A11Y-003 (ChartContainer accessibility)', () => {
  it('renders the chart with role=img via ChartContainer', () => {
    render(
      <MetricTimeline series={baseSeries} annotations={[]} meta={baseMeta} />,
    );
    // ChartContainer renders a div[role="img"] — assert it's present
    expect(screen.getByRole('img')).toBeInTheDocument();
  });

  it('sets a meaningful aria-label on the chart (F5A11Y-003)', () => {
    render(
      <MetricTimeline series={baseSeries} annotations={[]} meta={baseMeta} />,
    );
    const chart = screen.getByRole('img');
    expect(chart).toHaveAttribute(
      'aria-label',
      'Traffic timeline: clicks, impressions, and position from 2026-01-01 to 2026-03-31',
    );
  });

  it('renders the ChartDataTable companion for non-visual access', () => {
    render(
      <MetricTimeline series={baseSeries} annotations={[]} meta={baseMeta} />,
    );
    // ChartDataTable renders a "Show data table" toggle button
    expect(
      screen.getByRole('button', { name: /show data table/i }),
    ).toBeInTheDocument();
  });

  it('does not render a bare ResponsiveContainer directly (must go through ChartContainer)', () => {
    render(
      <MetricTimeline series={baseSeries} annotations={[]} meta={baseMeta} />,
    );
    // The outer wrapper should be a role=img div, not a bare responsive-container
    // ChartContainer wraps ResponsiveContainer — that's fine.
    // What we assert: the chart's accessible name is NOT missing ("Data chart" default means no custom label was passed)
    const chart = screen.getByRole('img');
    expect(chart).not.toHaveAttribute('aria-label', 'Data chart');
  });

  it('renders summary stats', () => {
    render(
      <MetricTimeline series={baseSeries} annotations={[]} meta={baseMeta} />,
    );
    expect(screen.getByText('Total Clicks')).toBeInTheDocument();
    expect(screen.getByText('Total Impressions')).toBeInTheDocument();
    expect(screen.getByText('Avg Position')).toBeInTheDocument();
  });

  it('renders metric toggle controls', () => {
    render(
      <MetricTimeline series={baseSeries} annotations={[]} meta={baseMeta} />,
    );
    // Radix ToggleGroup 1.1.x renders role="toolbar" (was "group" in older versions)
    expect(
      screen.getByRole('toolbar', { name: 'Toggle chart metrics' }),
    ).toBeInTheDocument();
    expect(screen.getByRole('button', { name: 'Toggle clicks series' })).toBeInTheDocument();
    expect(screen.getByRole('button', { name: 'Toggle impressions series' })).toBeInTheDocument();
    expect(screen.getByRole('button', { name: 'Toggle position series' })).toBeInTheDocument();
  });

  it('renders annotations list when annotations are provided', () => {
    const annotations = [
      {
        date: '2026-01-15',
        type: 'recommendation',
        title: 'Content updated',
        description: 'Added new section',
        link: null,
        entity_id: null,
      },
    ];
    render(
      <MetricTimeline series={baseSeries} annotations={annotations} meta={baseMeta} />,
    );
    expect(screen.getByText('Events')).toBeInTheDocument();
    expect(screen.getByText('Content updated')).toBeInTheDocument();
  });

  it('does not render annotations section when annotations are empty', () => {
    render(
      <MetricTimeline series={baseSeries} annotations={[]} meta={baseMeta} />,
    );
    expect(screen.queryByText('Events')).not.toBeInTheDocument();
  });
});

describe('MetricTimeline — PROD-FIND-ANNOT-001 (algorithm_update markers)', () => {
  const algoUpdateAnnotation = {
    date: '2026-03-10',
    type: 'algorithm_update',
    title: 'March 2026 Core Update',
    description: 'Google Core Update',
    link: 'https://status.search.google.com/incidents/example',
    entity_id: null,
  };

  it('renders an algorithm_update annotation in the Events list', () => {
    render(
      <MetricTimeline
        series={baseSeries}
        annotations={[algoUpdateAnnotation]}
        meta={baseMeta}
      />,
    );
    expect(screen.getByText('Events')).toBeInTheDocument();
    expect(screen.getByText('March 2026 Core Update')).toBeInTheDocument();
  });

  it('renders a "Google Update" type badge for algorithm_update', () => {
    render(
      <MetricTimeline
        series={baseSeries}
        annotations={[algoUpdateAnnotation]}
        meta={baseMeta}
      />,
    );
    // The badge aria-label is "Event type: Google Update"
    expect(
      screen.getByLabelText('Event type: Google Update'),
    ).toBeInTheDocument();
    expect(screen.getByLabelText('Event type: Google Update')).toHaveTextContent(
      'Google Update',
    );
  });

  it('renders an external link to the Google announcement for algorithm_update', () => {
    render(
      <MetricTimeline
        series={baseSeries}
        annotations={[algoUpdateAnnotation]}
        meta={baseMeta}
      />,
    );
    const link = screen.getByRole('link', { name: /google announcement/i });
    expect(link).toBeInTheDocument();
    expect(link).toHaveAttribute('href', algoUpdateAnnotation.link);
    expect(link).toHaveAttribute('target', '_blank');
    expect(link).toHaveAttribute('rel', 'noopener noreferrer');
  });

  it('does not render a Google announcement link when link is null', () => {
    const noLinkAnnotation = { ...algoUpdateAnnotation, link: null };
    render(
      <MetricTimeline
        series={baseSeries}
        annotations={[noLinkAnnotation]}
        meta={baseMeta}
      />,
    );
    expect(screen.queryByRole('link', { name: /google announcement/i })).not.toBeInTheDocument();
  });

  it('renders a "Recommendation" type badge for recommendation type (distinct from algorithm_update)', () => {
    const recAnnotation = {
      date: '2026-01-15',
      type: 'recommendation',
      title: 'Content rewrite applied',
      description: 'Rewrote introduction',
      link: null,
      entity_id: 42,
    };
    render(
      <MetricTimeline
        series={baseSeries}
        annotations={[recAnnotation]}
        meta={baseMeta}
      />,
    );
    expect(
      screen.getByLabelText('Event type: Recommendation'),
    ).toBeInTheDocument();
    // Must NOT show "Google Update" badge
    expect(screen.queryByLabelText('Event type: Google Update')).not.toBeInTheDocument();
  });

  it('renders both an algorithm_update and a recommendation as separate events', () => {
    const recAnnotation = {
      date: '2026-01-15',
      type: 'recommendation',
      title: 'Content rewrite applied',
      description: 'Rewrote introduction',
      link: null,
      entity_id: 42,
    };
    render(
      <MetricTimeline
        series={baseSeries}
        annotations={[recAnnotation, algoUpdateAnnotation]}
        meta={baseMeta}
      />,
    );
    expect(screen.getByText('Content rewrite applied')).toBeInTheDocument();
    expect(screen.getByText('March 2026 Core Update')).toBeInTheDocument();
    expect(screen.getByLabelText('Event type: Recommendation')).toBeInTheDocument();
    expect(screen.getByLabelText('Event type: Google Update')).toBeInTheDocument();
  });
});

describe('MetricTimeline — PROD-R16-02 (AI impressions series)', () => {
  const metaWithGenAi = {
    ...baseMeta,
    gen_ai_impressions: [
      { date: '2026-01-01', impressions: 320 },
      { date: '2026-01-08', impressions: 415 },
    ],
  };

  it('renders an "AI Impressions" toggle button when gen_ai_impressions are present', () => {
    render(
      <MetricTimeline series={baseSeries} annotations={[]} meta={metaWithGenAi} />,
    );
    expect(
      screen.getByRole('button', { name: 'Toggle AI impressions series' }),
    ).toBeInTheDocument();
  });

  it('does NOT render an "AI Impressions" toggle when gen_ai_impressions is absent', () => {
    render(
      <MetricTimeline series={baseSeries} annotations={[]} meta={baseMeta} />,
    );
    expect(
      screen.queryByRole('button', { name: 'Toggle AI impressions series' }),
    ).not.toBeInTheDocument();
  });

  it('does NOT render an "AI Impressions" toggle when gen_ai_impressions is empty array', () => {
    render(
      <MetricTimeline
        series={baseSeries}
        annotations={[]}
        meta={{ ...baseMeta, gen_ai_impressions: [] }}
      />,
    );
    expect(
      screen.queryByRole('button', { name: 'Toggle AI impressions series' }),
    ).not.toBeInTheDocument();
  });

  it('updates the chart aria-label to mention AI impressions when gen_ai data is present', () => {
    render(
      <MetricTimeline series={baseSeries} annotations={[]} meta={metaWithGenAi} />,
    );
    const chart = screen.getByRole('img');
    expect(chart).toHaveAttribute(
      'aria-label',
      'Traffic timeline: clicks, impressions, AI impressions, and position from 2026-01-01 to 2026-03-31',
    );
  });

  it('includes AI Impressions column in the accessible data table when gen_ai data is present', () => {
    render(
      <MetricTimeline series={baseSeries} annotations={[]} meta={metaWithGenAi} />,
    );
    // Expand the data table
    const showButton = screen.getByRole('button', { name: /show data table/i });
    showButton.click();
    // The data table column header is a <th> element — use getByRole to narrow to the table header
    expect(screen.getByRole('columnheader', { name: 'AI Impressions' })).toBeInTheDocument();
  });
});

describe('MetricTimeline — R7FE-006 empty/single-point guards', () => {
  it('R7FE-006: renders a "No traffic data" status message for empty series', () => {
    render(
      <MetricTimeline series={[]} annotations={[]} meta={baseMeta} />,
    );
    expect(screen.getByRole('status')).toBeInTheDocument();
    expect(screen.getByText(/no traffic data/i)).toBeInTheDocument();
  });

  it('R7FE-006: does NOT render a chart or toggles for empty series', () => {
    render(
      <MetricTimeline series={[]} annotations={[]} meta={baseMeta} />,
    );
    expect(screen.queryByRole('img')).not.toBeInTheDocument();
    expect(screen.queryByRole('group', { name: 'Toggle chart metrics' })).not.toBeInTheDocument();
  });

  it('R7FE-006: renders the chart (not empty status) for a single-point series', () => {
    const singleSeries = [{ date: '2026-01-01', clicks: 100, impressions: 4000, position: 11.2 }];
    render(
      <MetricTimeline series={singleSeries} annotations={[]} meta={baseMeta} />,
    );
    // Should render the chart, not the empty state.
    expect(screen.queryByRole('status')).not.toBeInTheDocument();
    expect(screen.getByRole('img')).toBeInTheDocument();
  });
});
