import { Skeleton } from '@/components/ui/skeleton';
import { useTheme } from '@/context/theme-context';
import { useApiSWR } from '@/hooks/useSWR';
import dayjs from 'dayjs';
import { Suspense, useEffect, useRef, useState } from 'react';
import Chart from 'react-apexcharts';
import { useTranslation } from 'react-i18next';

type ChartSeries = {
  name: string;
  color: string;
  data: [number, number][];
};

export type ProbabilityHistoryData = {
  series: ChartSeries[];
  changes: Record<number, number | null>;
};

const RANGES = [
  { label: '24H', hours: 24 },
  { label: '7D', hours: 24 * 7 },
  { label: '30D', hours: 24 * 30 },
  { label: 'All', hours: Infinity },
] as const;

interface MarketProbabilityChartProps {
  slug: string;
  onData?: (data: ProbabilityHistoryData) => void;
  // When set, show only this outcome's line (by title), Polymarket-style:
  // right-hand auto-scaled axis, no legend, a dot on the latest point.
  focusName?: string;
  // Embed knobs (used by the embeddable widget).
  hideRange?: boolean;
  showYAxis?: boolean;
  showGrid?: boolean;
  height?: number;
  dark?: boolean; // force theme regardless of the viewer's setting
}

export default function MarketProbabilityChart({
  slug,
  onData,
  focusName,
  hideRange = false,
  showYAxis = true,
  showGrid = true,
  height = 240,
  dark,
}: MarketProbabilityChartProps) {
  const { t } = useTranslation();
  const { theme } = useTheme();
  const [range, setRange] = useState<(typeof RANGES)[number]>(RANGES[1]);
  const [hovered, setHovered] = useState(false);
  const wrapRef = useRef<HTMLDivElement>(null);
  const dateRef = useRef<HTMLDivElement>(null);

  const { data, isLoading } = useApiSWR<ProbabilityHistoryData>(
    slug ? `/markets/${slug}/probability-history` : null,
  );

  useEffect(() => {
    if (data && onData) onData(data);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [data]);

  // Keep all points and window the view via xaxis.range (like the featured
  // chart panel). Filtering client-side would drop the synthetic starting
  // point for markets older than the selected range, leaving a single point
  // that renders as "Not enough data".
  const allSeries = (data?.series ?? []).map((s) => ({
    name: s.name,
    color: s.color,
    data: s.data,
  }));

  const series = focusName
    ? allSeries.filter((s) => s.name === focusName)
    : allSeries;

  const xaxisRange =
    range.hours === Infinity ? undefined : range.hours * 60 * 60 * 1000;

  const colors = series.map((s) => s.color);

  // Latest point of each line — used for the end-of-line dot + pill label and
  // the "latest %" shown in the legend (Polymarket style).
  const lastPoints = series
    .map((s) => {
      if (!s.data.length) return null;
      const [x, y] = s.data[s.data.length - 1];
      return { name: s.name, color: s.color, x, y };
    })
    .filter((p): p is { name: string; color: string; x: number; y: number } =>
      Boolean(p),
    );

  const isDark = dark ?? theme === 'dark';
  const textColor = isDark ? 'rgba(255,255,255,0.45)' : 'rgba(0,0,0,0.45)';
  const gridColor = isDark ? 'rgba(255,255,255,0.08)' : 'rgba(0,0,0,0.07)';

  const options: ApexCharts.ApexOptions = {
    chart: {
      type: 'line',
      background: 'transparent',
      toolbar: { show: false },
      zoom: { enabled: false },
      animations: { enabled: true, speed: 400 },
      events: {
        // Render the hovered date as a small label pinned to the top of the
        // chart, following the crosshair x (Polymarket style). Done via refs
        // so pointer movement never triggers a React re-render.
        mouseMove: (event, ctx, cfg) => {
          const el = dateRef.current;
          const wrap = wrapRef.current;
          if (!el || !wrap) return;
          const idx = cfg?.dataPointIndex ?? -1;
          const xs = ctx?.w?.globals?.seriesX?.[0];
          const ts = idx >= 0 && xs ? xs[idx] : undefined;
          if (ts == null) {
            el.style.opacity = '0';
            return;
          }
          const rect = wrap.getBoundingClientRect();
          const mouseEvent = event as MouseEvent;
          const x = Math.min(
            Math.max(mouseEvent.clientX - rect.left, 48),
            rect.width - 48,
          );
          el.textContent = dayjs(ts).format('MMM D, HH:mm');
          el.style.left = `${x}px`;
          el.style.opacity = '1';
        },
        mouseLeave: () => {
          if (dateRef.current) dateRef.current.style.opacity = '0';
        },
      },
    },
    colors,
    stroke: {
      curve: 'straight',
      width: 2,
      lineCap: 'round',
    },
    xaxis: {
      type: 'datetime',
      range: xaxisRange,
      labels: {
        datetimeUTC: false,
        style: { colors: textColor, fontSize: '11px' },
      },
      axisBorder: { show: false },
      axisTicks: { show: false },
      crosshairs: {
        show: true,
        stroke: { color: gridColor, width: 1, dashArray: 0 },
      },
      tooltip: { enabled: false },
    },
    yaxis: {
      show: showYAxis,
      opposite: true,
      forceNiceScale: true,
      min: 0,
      tickAmount: 4,
      labels: {
        formatter: (v) => `${Math.round(v)}%`,
        style: { colors: textColor, fontSize: '11px' },
      },
    },
    markers: { size: 0, hover: { size: 5 } },
    annotations: {
      points: lastPoints.map((p) => ({
        x: p.x,
        y: p.y,
        marker: {
          size: 4,
          fillColor: p.color,
          strokeColor: isDark ? '#0b0b0f' : '#ffffff',
          strokeWidth: 2,
          cssClass: 'pm-pulse-dot',
        },
        // Pill label with the outcome name + latest % is revealed only while
        // the chart is hovered (Polymarket style). Otherwise just the dot.
        ...(hovered && {
          label: {
            text: `${p.name} ${p.y.toFixed(1)}%`,
            borderColor: 'transparent',
            borderWidth: 0,
            offsetX: 2,
            offsetY: 0,
            textAnchor: 'start',
            style: {
              background: p.color,
              color: '#ffffff',
              fontSize: '11px',
              fontWeight: 600,
              padding: { left: 6, right: 6, top: 3, bottom: 3 },
            },
          },
        }),
      })),
    },
    grid: {
      borderColor: gridColor,
      strokeDashArray: 4,
      padding: { left: 4, right: showYAxis ? 96 : 8, top: 8 },
      xaxis: { lines: { show: false } },
      yaxis: { lines: { show: showGrid } },
    },
    dataLabels: { enabled: false },
    legend: {
      show: series.length > 1,
      position: 'top',
      horizontalAlign: 'left',
      fontSize: '13px',
      fontWeight: 600,
      labels: { colors: textColor },
      markers: { size: 6, offsetX: -2 },
      itemMargin: { horizontal: 10, vertical: 2 },
      formatter: (seriesName) => {
        const p = lastPoints.find((lp) => lp.name === seriesName);
        return p ? `${seriesName}  ${Math.round(p.y)}%` : seriesName;
      },
    },
    // Keep the tooltip system enabled so the crosshair + mouseMove events fire,
    // but hide the default multi-series box (see `.pm-chart .apexcharts-tooltip`
    // in the style tag). The hovered date is shown by the top overlay instead.
    tooltip: {
      enabled: true,
      shared: true,
      intersect: false,
      custom: () => '',
    },
  };

  if (isLoading) {
    return <Skeleton style={{ height }} className="w-full rounded-xl" />;
  }

  const hasData = series.some((s) => s.data.length > 1);

  if (!hasData) {
    return (
      <div
        style={{ height }}
        className="flex items-center justify-center text-sm text-black/40 dark:text-white/40"
      >
        {t('Not enough data yet. Check back after trading begins.')}
      </div>
    );
  }

  return (
    <div>
      {!hideRange && (
        <div className="mb-3 flex justify-end gap-1">
          {RANGES.map((r) => (
            <button
              key={r.label}
              onClick={() => setRange(r)}
              className={`rounded-md px-2.5 py-1 text-xs font-medium transition-colors ${
                range.label === r.label
                  ? 'bg-black/10 text-black dark:bg-white/10 dark:text-white'
                  : 'text-black/40 hover:text-black/70 dark:text-white/40 dark:hover:text-white/70'
              }`}
            >
              {r.label}
            </button>
          ))}
        </div>
      )}
      <style>{`
        @keyframes pm-pulse {
          0%, 100% { opacity: 1; }
          50% { opacity: 0.2; }
        }
        .pm-pulse-dot { animation: pm-pulse 1.4s ease-in-out infinite; }
        .pm-chart .apexcharts-tooltip { display: none !important; }
      `}</style>
      <div
        ref={wrapRef}
        className="pm-chart relative"
        onMouseEnter={() => setHovered(true)}
        onMouseLeave={() => setHovered(false)}
      >
        <div
          ref={dateRef}
          className="pointer-events-none absolute top-0 z-10 -translate-x-1/2 rounded-md bg-black/75 px-2 py-1 text-[11px] font-medium whitespace-nowrap text-white opacity-0 transition-opacity dark:bg-white/85 dark:text-black"
          style={{ left: 0 }}
        />
        <Suspense
          fallback={
            <Skeleton style={{ height }} className="w-full rounded-xl" />
          }
        >
          <Chart
            options={options}
            series={series}
            type="line"
            width="100%"
            height={height}
          />
        </Suspense>
      </div>
    </div>
  );
}
