/**
 * ComparisonChart Component
 * Multi-school comparison chart using Chart.js.
 *
 * Desktop: built-in legend (point-style markers double as per-school shapes).
 * Mobile (≤640px): the in-chart legend and axis titles are dropped in favour
 *   of a chip row above the canvas; tapping a chip highlights that school's
 *   line and dims the rest. The y-axis auto-fits the data on all viewports so
 *   clustered schools stay distinguishable.
 */

'use client';

import { useEffect, useState } from 'react';
import { Line } from 'react-chartjs-2';
import { ChartOptions, ChartDataset, PointStyle } from 'chart.js';
import '@/lib/chartSetup';
import { useSeriesColors, useThemeTokens } from '@/lib/theme';
import { buildCompareChart } from '@/lib/compareChartData';
import type { ComparisonData } from '@/lib/types';
import {
  CHART_COLORS,
  CHART_TEXT_COLORS,
  computeYBounds,
  formatAcademicYear,
  metricKind,
  rgbToRgba,
} from '@/lib/utils';
import { useIsMobile } from '@/hooks/useIsMobile';
import { track } from '@/lib/analytics';
import styles from './ComparisonChart.module.css';

interface ComparisonChartProps {
  comparisonData: Record<string, ComparisonData>;
  /** Ordered as displayed in the school cards, so colours match by index. */
  schools: Array<{ urn: number; school_name: string }>;
  metric: string;
  metricLabel: string;
  /** Official England figure per academic year for this metric — renders a
   * dashed grey reference line when provided. */
  nationalByYear?: Record<number, number | null | undefined>;
  /** KS4 metrics get a different (honest) gap caption than KS2. */
  isSecondary?: boolean;
}

// One shape per basket slot (MAX_SCHOOLS = 5) — secondary encoding so
// converging lines stay tellable apart without relying on hue alone.
const POINT_STYLES: PointStyle[] = ['circle', 'triangle', 'rect', 'rectRot', 'star'];

export function ComparisonChart({ comparisonData, schools, metric, metricLabel, nationalByYear, isSecondary = false }: ComparisonChartProps) {
  const isMobile = useIsMobile();
  // Canvas can't resolve var(), so the series come through the token bridge.
  // Same index order as CHART_COLORS, so a school's line and its DOM swatch
  // stay the same colour.
  const seriesColors = useSeriesColors();
  const [cRef, cGrid, cInverse, cInverseText] = useThemeTokens(
    '--chart-reference', '--chart-grid', '--surface-inverse', '--text-inverse'
  );
  const [focusedUrn, setFocusedUrn] = useState<number | null>(null);

  // A focused school that leaves the basket must not linger.
  const urnKey = schools.map((s) => s.urn).join(',');
  useEffect(() => {
    setFocusedUrn(null);
  }, [urnKey]);

  if (schools.length === 0) {
    return <div>No data available</div>;
  }

  // Pure, tested series construction: union of years with cancelled /
  // unpublished years kept as real gaps, plus the England overlay.
  const built = buildCompareChart(comparisonData, schools, metric, nationalByYear);
  const { years } = built;

  const datasets: ChartDataset<'line'>[] = built.schoolDatasets.map((series) => {
    const school = schools[series.schoolIndex];
    const color = seriesColors[series.schoolIndex % seriesColors.length];
    const dimmed = focusedUrn !== null && focusedUrn !== school.urn;

    return {
      label: series.label,
      data: series.data,
      borderColor: dimmed ? rgbToRgba(color, 0.2) : color,
      backgroundColor: dimmed ? 'transparent' : rgbToRgba(color, 0.1),
      borderWidth: focusedUrn === school.urn ? 3 : dimmed ? 1.5 : 2,
      pointStyle: POINT_STYLES[series.schoolIndex % POINT_STYLES.length],
      pointRadius: dimmed ? 2 : isMobile ? 3 : 4,
      pointHoverRadius: isMobile ? 5 : 6,
      tension: 0.3,
      // Never bridge missing years — gaps are information (COVID
      // cancellations, unpublished 2021/22, schools that opened later).
      spanGaps: false,
    };
  });

  if (built.englandDataset) {
    datasets.push({
      label: built.englandDataset.label,
      data: built.englandDataset.data,
      borderColor: cRef,
      backgroundColor: 'transparent',
      borderWidth: 1.5,
      borderDash: built.englandDataset.borderDash,
      pointStyle: 'line',
      pointRadius: 0,
      pointHoverRadius: 4,
      tension: 0,
      spanGaps: false,
    });
  }

  const chartData = {
    labels: years.map(formatAcademicYear),
    datasets,
  };

  const kind = metricKind(metric);
  const yBounds = computeYBounds(
    datasets.flatMap((ds) => ds.data as Array<number | null>),
    kind,
  );

  const options: ChartOptions<'line'> = {
    responsive: true,
    maintainAspectRatio: false,
    interaction: {
      mode: 'index' as const,
      intersect: false,
    },
    plugins: {
      legend: {
        display: !isMobile,
        position: 'top' as const,
        labels: {
          usePointStyle: true,
          padding: 15,
          font: {
            size: 12,
          },
        },
      },
      // No in-chart title: the section heading and metric selector above the
      // chart already state the metric.
      title: {
        display: false,
      },
      tooltip: {
        backgroundColor: cInverse,
        titleColor: cInverseText,
        bodyColor: cInverseText,
        padding: isMobile ? 10 : 12,
        titleFont: {
          size: isMobile ? 12 : 14,
        },
        bodyFont: {
          size: isMobile ? 11 : 13,
        },
        usePointStyle: true,
        itemSort: (a, b) => (b.parsed.y ?? -Infinity) - (a.parsed.y ?? -Infinity),
        callbacks: {
          label: function (context) {
            let label = context.dataset.label || '';
            if (label) {
              label += ': ';
            }
            if (context.parsed.y !== null) {
              label += context.parsed.y.toFixed(1) + (kind === 'percentage' ? '%' : '');
            } else {
              label += 'N/A';
            }
            return label;
          },
        },
      },
    },
    scales: {
      y: {
        type: 'linear' as const,
        display: true,
        title: {
          display: !isMobile,
          text: kind === 'percentage' ? 'Percentage (%)' : kind === 'progress' ? 'Progress Score' : 'Score',
          font: {
            size: 12,
            weight: 'bold',
          },
        },
        ...yBounds,
        ticks: {
          font: { size: isMobile ? 10 : 12 },
          ...(isMobile && { maxTicksLimit: 5 }),
        },
        grid: {
          color: cGrid,
        },
      },
      x: {
        grid: {
          display: false,
        },
        title: {
          display: !isMobile,
          text: 'Year',
          font: {
            size: 12,
            weight: 'bold',
          },
        },
        ticks: {
          font: { size: isMobile ? 10 : 12 },
          ...(isMobile && { maxRotation: 0, autoSkip: true, maxTicksLimit: 4 }),
        },
      },
    },
  };

  const toggleFocus = (urn: number) => {
    const next = focusedUrn === urn ? null : urn;
    setFocusedUrn(next);
    if (next !== null) track('compare_focus_school', { urn: next });
  };

  return (
    <div className={styles.wrapper}>
      {/* Mobile legend + focus control; a single series needs no legend. */}
      {schools.length > 1 && (
        <div className={styles.chips} role="group" aria-label="Highlight a school on the chart">
          {schools.map((school, index) => (
            <button
              key={school.urn}
              type="button"
              className={styles.chip}
              aria-pressed={focusedUrn === school.urn}
              onClick={() => toggleFocus(school.urn)}
            >
              <span
                className={styles.chipDot}
                style={{ background: CHART_COLORS[index % CHART_COLORS.length] }}
                aria-hidden="true"
              />
              <span
                className={styles.chipName}
                style={{ color: CHART_TEXT_COLORS[index % CHART_TEXT_COLORS.length] }}
              >
                {school.school_name}
              </span>
            </button>
          ))}
        </div>
      )}
      <div className={styles.canvasBox}>
        <Line data={chartData} options={options} aria-label={`${metricLabel} comparison chart`} />
      </div>
      {isSecondary && built.englandOnlyYears.length > 0 ? (
        // KS4's honest story differs from KS2's: 2019/20–2020/21 school-level
        // GCSE results weren't published (COVID grading); later years WERE
        // published by DfE but aren't in our dataset yet.
        <p className={styles.chartNote}>
          School-level GCSE figures for 2019/20 and 2020/21 weren&apos;t published (COVID
          grading), and more recent years aren&apos;t in our dataset yet where lines break — the
          England average is shown where available.
        </p>
      ) : (
        !isSecondary &&
        built.showUnpublished202122Note && (
          <p className={styles.chartNote}>
            No national tests were held in 2019/20 and 2020/21 (COVID), and DfE didn&apos;t publish
            school-level figures for 2021/22 — the England average is shown for that year.
          </p>
        )
      )}
    </div>
  );
}
