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, getRegimeMonitor } 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 boundaries come from the backend v2 methodology response.
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">
        State <span className="text-blue-300">{Math.round(p.x)}</span> · 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(800) });
  const monitor = useQuery({ queryKey: ['regime', 'monitor'], queryFn: getRegimeMonitor });
  const xDiv = monitor.data?.quadrant_config?.state_divider ?? 60;
  const yDiv = monitor.data?.quadrant_config?.warning_divider ?? 60;

  const points = useMemo<QPoint[]>(() => {
    const data = history.data ?? [];
    return data
      .filter((p) => p.state != null && p.warning != null)
      .slice(-TRAIL)
      .map((p) => ({ x: p.state as number, y: p.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">
          State × Warning quadrant — last {TRAIL} sessions
        </div>
        {latest && (
          <div className="text-[11px] text-gray-500">
            now: State <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 coverage-qualified v2 history yet.
        </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={xDiv} y1={yDiv} y2={100} fill="#f59e0b" fillOpacity={0.07} stroke="none" />
                <ReferenceArea x1={xDiv} x2={100} y1={yDiv} y2={100} fill="#f97316" fillOpacity={0.07} stroke="none" />
                <ReferenceArea x1={0} x2={xDiv} y1={0} y2={yDiv} fill="#10b981" fillOpacity={0.07} stroke="none" />
                <ReferenceArea x1={xDiv} x2={100} y1={0} y2={yDiv} fill="#ef4444" fillOpacity={0.08} stroke="none" />
                <CartesianGrid stroke="rgba(255,255,255,0.04)" />
                <ReferenceLine x={xDiv} stroke="rgba(255,255,255,0.12)" />
                <ReferenceLine y={yDiv} 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: 'State →', 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: '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">Early warning</span> — state calm, fragility rising</span>
            <span><span className="text-orange-400">Active stress</span> — damaged and deteriorating</span>
            <span><span className="text-emerald-400">Healthy</span> — calm and broadly supported</span>
            <span><span className="text-red-400">Stressed / stabilizing</span> — damage remains, warning lower</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 path matters more than a single point. Risk thermometer — not an entry, exit,
            or sizing signal.
          </p>
        </>
      )}
    </div>
  );
}
