"use client";

import React from "react";
import { motion, useTransform, type MotionValue } from "framer-motion";
import { COLORS, KPIS, Kpi, rgba } from "./constants";

type Props = {
  /** shared scroll progress (0 → 1) */
  scroll: MotionValue<number>;
};

const COUNT_START = 0.7;
const COUNT_END = 0.97;

function Metric({ kpi, scroll, index, jitter }: { kpi: Kpi; scroll: MotionValue<number>; index: number; jitter: number }) {
  // Single reactive string — updates without re-rendering React.
  const value = useTransform(scroll, (v) => {
    const t = Math.min(1, Math.max(0, (v - COUNT_START) / (COUNT_END - COUNT_START)));
    let n = kpi.before + (kpi.after - kpi.before) * t;

    // Apply high-frequency live operational fluctuations on settled state
    if (t > 0.95) {
      n = n * (1 + jitter);
    }

    const afterSide = t > 0.5;
    const prefix = afterSide ? kpi.prefixAfter ?? "" : kpi.prefixBefore ?? "";

    if (kpi.key === "delayed" && kpi.after === 0 && t > 0.95) {
      return `0`;
    }

    return `${prefix}${Math.round(n)}${kpi.suffix ?? ""}`;
  });

  const label = useTransform(scroll, (v) =>
    v > (COUNT_START + COUNT_END) / 2 ? kpi.labelAfter : kpi.labelBefore,
  );

  const fromColor = kpi.key === "orders" ? COLORS.cyan : COLORS.red;
  const toColor = COLORS.green;
  const accent = useTransform(
    scroll,
    [COUNT_START, COUNT_END],
    [rgba(fromColor, 1), rgba(toColor, 1)],
  );
  const glow = useTransform(
    scroll,
    [COUNT_START, COUNT_END],
    [rgba(fromColor, 0.28), rgba(toColor, 0.32)],
  );
  const boxShadow = useTransform(glow, (g) => `0 10px 40px -12px ${g}, inset 0 1px 0 rgba(255,255,255,0.06)`);
  const borderColor = useTransform(
    scroll,
    [COUNT_START, COUNT_END],
    [rgba(fromColor, 0.4), rgba(toColor, 0.45)],
  );

  // Improvement arrow appears once optimized.
  const arrowOpacity = useTransform(scroll, [COUNT_END - 0.12, COUNT_END], [0, 1]);
  // Bar fills as the counter morphs from before → after.
  const fillScale = useTransform(scroll, [COUNT_START, COUNT_END], [0.12, 1]);

  const trendColor = kpi.goodWhenLower ? COLORS.green : (kpi.key === "orders" ? COLORS.cyan : COLORS.green);

  const sparklinePath = React.useMemo(() => {
    switch (kpi.key) {
      case "distance":
      case "vehicles":
        return "M 0,3 C 16,3 32,17 64,17"; // Downward trend
      case "orders":
        return "M 0,17 C 16,6 32,19 64,8"; // Stable high wavy trend
      case "delayed":
      case "cost":
        return "M 0,1 C 16,1 28,19 64,19"; // Sharp drop
      default:
        return "M 0,10 L 64,10";
    }
  }, [kpi.key]);

  return (
    <motion.div
      className="dm-opt-metric"
      style={{ boxShadow, borderColor, animationDelay: `${0.06 * index}s` }}
    >
      <div className="dm-opt-metric__top">
        <motion.span className="dm-opt-metric__label">{label}</motion.span>
        <motion.span className="dm-opt-metric__arrow" style={{ opacity: arrowOpacity, color: COLORS.green }}>
          {kpi.goodWhenLower ? "▼" : "▲"}
        </motion.span>
      </div>
      <motion.div className="dm-opt-metric__value" style={{ color: accent }}>
        {value}
      </motion.div>
      
      {/* Sparkline trend graphic */}
      <div className="dm-opt-metric__sparkline" style={{ position: "absolute", bottom: 8, right: 12, opacity: 0.32, width: 64, height: 20, pointerEvents: "none" }}>
        <svg width="100%" height="100%" viewBox="0 0 64 20" fill="none">
          <defs>
            <linearGradient id={`grad-${kpi.key}`} x1="0" y1="0" x2="0" y2="20" gradientUnits="userSpaceOnUse">
              <stop offset="0%" stopColor={trendColor} stopOpacity="0.22" />
              <stop offset="100%" stopColor={trendColor} stopOpacity="0.0" />
            </linearGradient>
          </defs>
          <path
            d={sparklinePath}
            stroke={trendColor}
            strokeWidth="1.2"
            strokeLinecap="round"
            strokeLinejoin="round"
          />
          <path
            d={`${sparklinePath} L 64,20 L 0,20 Z`}
            fill={`url(#grad-${kpi.key})`}
          />
        </svg>
      </div>

      <div className="dm-opt-metric__bar">
        <motion.div
          className="dm-opt-metric__fill"
          style={{ background: accent, scaleX: fillScale }}
        />
      </div>
    </motion.div>
  );
}

const MetricCard = React.memo(Metric);

function MetricsPanel({ scroll }: Props) {
  // One shared interval drives the live "operational" micro-fluctuation for all
  // cards (was 5 independent timers). Paused under reduced-motion and when the
  // tab is hidden.
  const [jitters, setJitters] = React.useState<number[]>(() => KPIS.map(() => 0));

  React.useEffect(() => {
    if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
    const id = setInterval(() => {
      if (document.hidden) return;
      setJitters(KPIS.map(() => (Math.random() - 0.5) * 0.008));
    }, 1100);
    return () => clearInterval(id);
  }, []);

  return (
    <div className="dm-opt-metrics" role="group" aria-label="Optimization results">
      {KPIS.map((kpi, i) => (
        <MetricCard key={kpi.key} kpi={kpi} scroll={scroll} index={i} jitter={jitters[i]} />
      ))}
    </div>
  );
}

export default React.memo(MetricsPanel);
