import { useMemo } from 'react';
import { useQuery } from '@tanstack/react-query';
import {
  ScatterChart,
  Scatter,
  Cell,
  XAxis,
  YAxis,
  ZAxis,
  CartesianGrid,
  Tooltip,
  ResponsiveContainer,
  ReferenceLine,
  ReferenceArea,
} from 'recharts';
import { getRegimeHistory } from '../../api/regime';
import { Callout } from '../ui/Callout';
import { SkeletonCard } from '../ui/Skeleton';

// Lazy-loaded (see RegimePage) so recharts stays in the regime-tab chunk.

// Quadrant dividers. Regime < 40 ≈ intact; early-warning > 60 ≈ elevated.
const X_DIV = 40; // regime index
const Y_DIV = 60; // early warning
const TRAIL = 60; // sessions shown

interface QPoint {
  x: number;
  y: number;
  date: string;
}

/** Centered moving average to de-noise the path; today (last) kept exact. */
function smoothTrail(points: QPoint[], half = 2): QPoint[] {
  const n = points.length;
  return points.map((p, i) => {
    if (i === n - 1) return { ...p };
    let sx = 0;
    let sy = 0;
    let c = 0;
    for (let j = Math.max(0, i - half); j <= Math.min(n - 1, i + half); j++) {
      sx += points[j].x;
      sy += points[j].y;
      c += 1;
    }
    return { x: sx / c, y: sy / c, date: p.date };
  });
}

/** Recency gradient: 0 = oldest (muted slate), 1 = newest (bright blue). */
function recencyColor(t: number): string {
  const lerp = (a: number, b: number) => Math.round(a + (b - a) * t);
  const r = lerp(71, 96);
  const g = lerp(85, 165);
  const b = lerp(105, 250);
  const alpha = (0.3 + 0.7 * t).toFixed(2);
  return `rgba(${r}, ${g}, ${b}, ${alpha})`;
}

function QuadrantTip({ active, payload }: { active?: boolean; payload?: { payload: QPoint }[] }) {
  if (!active || !payload?.length) return null;
  const p = payload[0].payload;
  return (
    <div className="glass px-2.5 py-1.5 text-[11px]">
      <div className="text-gray-300">{p.date}</div>
      <div className="text-gray-400">
        Regime <span className="text-blue-300">{Math.round(p.x)}</span> · Early warning{' '}
        <span className="text-orange-300">{Math.round(p.y)}</span>
      </div>
    </div>
  );
}

export default function RegimeQuadrant() {
  const history = useQuery({ queryKey: ['regime', 'history'], queryFn: () => getRegimeHistory(400) });

  const points = useMemo<QPoint[]>(() => {
    const data = history.data ?? [];
    return data
      .filter((p) => p.early_warning != null)
      .slice(-TRAIL)
      .map((p) => ({ x: p.index, y: p.early_warning as number, date: p.date }));
  }, [history.data]);

  const trail = useMemo(() => smoothTrail(points), [points]);
  const latest = points.length ? points[points.length - 1] : null;

  return (
    <div className="glass p-5">
      <div className="flex flex-wrap items-center justify-between gap-2">
        <div className="text-[11px] uppercase tracking-wider text-gray-500">
          Regime quadrant — last {TRAIL} sessions
        </div>
        {latest && (
          <div className="text-[11px] text-gray-500">
            now: regime <span className="text-blue-300">{Math.round(latest.x)}</span> · warning{' '}
            <span className="text-orange-300">{Math.round(latest.y)}</span>
          </div>
        )}
      </div>

      {history.isLoading ? (
        <SkeletonCard className="mt-3 h-72" />
      ) : !points.length ? (
        <Callout variant="empty">
          Not enough history yet — the early-warning fills in as the daily job runs.
        </Callout>
      ) : (
        <>
          <div className="mt-3 h-80">
            <ResponsiveContainer width="100%" height="100%">
              <ScatterChart margin={{ top: 10, right: 16, bottom: 22, left: 0 }}>
                {/* Quadrant shading (drawn first, behind everything) */}
                <ReferenceArea x1={0} x2={X_DIV} y1={Y_DIV} y2={100} fill="#f59e0b" fillOpacity={0.07} stroke="none" />
                <ReferenceArea x1={X_DIV} x2={100} y1={Y_DIV} y2={100} fill="#f97316" fillOpacity={0.07} stroke="none" />
                <ReferenceArea x1={0} x2={X_DIV} y1={0} y2={Y_DIV} fill="#10b981" fillOpacity={0.07} stroke="none" />
                <ReferenceArea x1={X_DIV} x2={100} y1={0} y2={Y_DIV} fill="#ef4444" fillOpacity={0.08} stroke="none" />
                <CartesianGrid stroke="rgba(255,255,255,0.04)" />
                <ReferenceLine x={X_DIV} stroke="rgba(255,255,255,0.12)" />
                <ReferenceLine y={Y_DIV} stroke="rgba(255,255,255,0.12)" />
                <XAxis
                  type="number"
                  dataKey="x"
                  domain={[0, 100]}
                  ticks={[0, 20, 40, 60, 80, 100]}
                  tick={{ fill: '#6b7280', fontSize: 10 }}
                  tickLine={false}
                  axisLine={{ stroke: 'rgba(255,255,255,0.08)' }}
                  label={{ value: 'Regime index →', position: 'insideBottom', offset: -12, fill: '#6b7280', fontSize: 10 }}
                />
                <YAxis
                  type="number"
                  dataKey="y"
                  domain={[0, 100]}
                  ticks={[0, 20, 40, 60, 80, 100]}
                  tick={{ fill: '#6b7280', fontSize: 10 }}
                  width={30}
                  tickLine={false}
                  axisLine={false}
                  label={{ value: 'Early warning', angle: -90, position: 'insideLeft', fill: '#6b7280', fontSize: 10 }}
                />
                <ZAxis range={[13, 13]} />
                <Tooltip cursor={{ strokeDasharray: '3 3', stroke: 'rgba(255,255,255,0.2)' }} content={<QuadrantTip />} />
                {/* Smoothed trail with a recency gradient (old → new) */}
                <Scatter
                  data={trail}
                  line={{ stroke: 'rgba(96,165,250,0.18)', strokeWidth: 1.5 }}
                  isAnimationActive={false}
                >
                  {trail.map((_, i) => (
                    <Cell key={i} fill={recencyColor(trail.length <= 1 ? 1 : i / (trail.length - 1))} />
                  ))}
                </Scatter>
                {/* Today */}
                {latest && (
                  <Scatter
                    data={[latest]}
                    isAnimationActive={false}
                    shape={(props: { cx?: number; cy?: number }) => (
                      <circle cx={props.cx} cy={props.cy} r={6} fill="#ffffff" stroke="#60a5fa" strokeWidth={2} />
                    )}
                  />
                )}
              </ScatterChart>
            </ResponsiveContainer>
          </div>

          <div className="mt-2 grid grid-cols-1 gap-x-4 gap-y-1 text-[11px] text-gray-500 sm:grid-cols-2">
            <span><span className="text-amber-400">① Hot &amp; brittle</span> — narrow melt-up, shakeout risk</span>
            <span><span className="text-orange-400">② Transition</span> — break may be starting</span>
            <span><span className="text-emerald-400">③ Healthy &amp; broad</span> — calm uptrend</span>
            <span><span className="text-red-400">④ Real downturn</span> — regime breaking, broad</span>
          </div>
          <p className="mt-2 text-[11px] leading-relaxed text-gray-600">
            White dot = today; the trail fades from muted (older) to bright blue (newer) over the last {TRAIL}{' '}
            sessions, smoothed. The tell isn&apos;t a single spot but the move ①→④ (early warning rolling over while
            the regime index climbs = divergence resolving downward). Observational — not wired into trades.
          </p>
        </>
      )}
    </div>
  );
}
