"use client";

/**
 * CASE CARD — distinct per case, photo-led with a tailored data viz.
 *   - Each card leads with its real SECTOR PHOTO (next/image -> WebP/AVIF, lazy,
 *     reserved aspect-ratio so no CLS). The image scales + parallax-drifts toward
 *     the pointer on hover.
 *   - Below the photo, a data visual UNIQUE to the case story:
 *       dual     -> CPA-down + ROAS-up twin lines (fashion)
 *       ramp     -> a slow-then-steep demo-requests line (SaaS)
 *       bookings -> monthly booking bars climbing toward a capacity target (clinic)
 *     The viz animates in on view (GSAP DrawSVG / CSS bar grow); no two alike.
 *   - 3D tilt that tracks the pointer via a soft spring; lift + accent shadow on
 *     hover; press dip. Transform-only.
 *   Reduced-motion / touch: flat card, static image, viz renders fully drawn.
 */
import { useEffect, useRef } from "react";
import Image from "next/image";
import {
  motion,
  useMotionValue,
  useSpring,
  useTransform,
  useReducedMotion,
} from "motion/react";
import { gsap } from "./gsap";
import { SPRING, EASE_OUT } from "./motion";

export type CaseData = {
  tag: string;
  image: string;
  alt: string;
  problem: string;
  result: string;
  how: string;
  metricNum: string;
  metricLabel: string;
  viz: "dual" | "ramp" | "bookings";
  series: number[];
  series2?: number[];
  target?: number;
  accent: string;
};

/* ---- viz geometry helpers (0..100 series mapped into a 240x96 box) ---- */
const VW = 240;
const VH = 96;
const VP = 10;
function toPoints(series: number[]) {
  const n = series.length;
  return series.map((v, i) => {
    const x = VP + (i / (n - 1)) * (VW - VP * 2);
    const y = VP + (1 - v / 100) * (VH - VP * 2);
    return { x, y };
  });
}
const poly = (series: number[]) =>
  toPoints(series)
    .map((p) => `${p.x},${p.y}`)
    .join(" ");

function CaseViz({ data }: { data: CaseData }) {
  const accent = data.accent;

  if (data.viz === "dual") {
    // CPA (falling, dashed) + ROAS (rising, solid) twin lines
    return (
      <svg className="case__chart" viewBox={`0 0 ${VW} ${VH}`} aria-hidden="true">
        <polyline
          className="case__line case__line--muted"
          points={poly(data.series)}
          fill="none"
          stroke="#9a9aac"
          strokeWidth="2"
          strokeDasharray="4 4"
          strokeLinecap="round"
        />
        <polyline
          className="case__line case__line--accent"
          points={poly(data.series2 ?? data.series)}
          fill="none"
          stroke={accent}
          strokeWidth="2.6"
          strokeLinecap="round"
          strokeLinejoin="round"
        />
        <g className="case__legend" fill="currentColor">
          <text x={VP} y={VH - 1}>CPA ↓</text>
          <text x={VW - VP} y={VH - 1} textAnchor="end" fill={accent}>ROAS ↑</text>
        </g>
      </svg>
    );
  }

  if (data.viz === "bookings") {
    // monthly bookings bars climbing toward a capacity target line
    const n = data.series.length;
    const gap = 6;
    const bw = (VW - VP * 2 - gap * (n - 1)) / n;
    const ty = VP + (1 - (data.target ?? 90) / 100) * (VH - VP * 2);
    return (
      <svg className="case__chart" viewBox={`0 0 ${VW} ${VH}`} aria-hidden="true">
        {/* target / capacity line */}
        <line
          className="case__target"
          x1={VP}
          y1={ty}
          x2={VW - VP}
          y2={ty}
          stroke={accent}
          strokeWidth="1.5"
          strokeDasharray="3 4"
        />
        <text className="case__targetlab" x={VW - VP} y={ty - 4} textAnchor="end" fill={accent}>
          capacity
        </text>
        {data.series.map((v, i) => {
          const h = (v / 100) * (VH - VP * 2);
          const x = VP + i * (bw + gap);
          const y = VH - VP - h;
          return (
            <rect
              key={i}
              className="case__bar2"
              x={x}
              y={y}
              width={bw}
              height={h}
              rx={2}
              fill={accent}
              style={{ ["--d" as string]: `${i * 80}ms` }}
            />
          );
        })}
      </svg>
    );
  }

  // ramp — slow-then-steep demo-requests line with an area fill
  const pts = toPoints(data.series);
  const linePts = poly(data.series);
  const area = `${linePts} ${VW - VP},${VH - VP} ${VP},${VH - VP}`;
  return (
    <svg className="case__chart" viewBox={`0 0 ${VW} ${VH}`} aria-hidden="true">
      <defs>
        <linearGradient id={`rampFill-${accent.slice(1)}`} x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stopColor={accent} stopOpacity="0.32" />
          <stop offset="100%" stopColor={accent} stopOpacity="0" />
        </linearGradient>
      </defs>
      <polygon className="case__area" points={area} fill={`url(#rampFill-${accent.slice(1)})`} />
      <polyline
        className="case__line case__line--accent"
        points={linePts}
        fill="none"
        stroke={accent}
        strokeWidth="2.6"
        strokeLinecap="round"
        strokeLinejoin="round"
      />
      <circle className="case__rampdot" cx={pts[pts.length - 1].x} cy={pts[pts.length - 1].y} r="3.5" fill={accent} />
    </svg>
  );
}

export default function CaseCard({
  data,
  index,
}: {
  data: CaseData;
  index: number;
}) {
  const reduce = useReducedMotion();
  const ref = useRef<HTMLDivElement>(null);
  const mx = useMotionValue(0.5);
  const my = useMotionValue(0.5);
  const rx = useSpring(useTransform(my, [0, 1], [5, -5]), SPRING.tilt);
  const ry = useSpring(useTransform(mx, [0, 1], [-6, 6]), SPRING.tilt);
  // image parallax — drifts opposite the tilt for depth
  const imgX = useSpring(useTransform(mx, [0, 1], [10, -10]), SPRING.tilt);
  const imgY = useSpring(useTransform(my, [0, 1], [10, -10]), SPRING.tilt);

  const onMove = (e: React.PointerEvent) => {
    if (reduce || e.pointerType !== "mouse") return;
    const el = ref.current;
    if (!el) return;
    const r = el.getBoundingClientRect();
    mx.set((e.clientX - r.left) / r.width);
    my.set((e.clientY - r.top) / r.height);
  };
  const reset = () => {
    mx.set(0.5);
    my.set(0.5);
  };

  // animate the viz in on view (lines draw, bars grow)
  useEffect(() => {
    const el = ref.current;
    if (!el || reduce) return;
    const ctx = gsap.context(() => {
      const lines = el.querySelectorAll(".case__line, .case__area, .case__target");
      gsap.from(lines, {
        drawSVG: "0%",
        duration: 1.1,
        ease: "power2.out",
        stagger: 0.12,
        scrollTrigger: { trigger: el, start: "top 82%", once: true },
        delay: 0.15 + index * 0.05,
      });
      gsap.from(el.querySelectorAll(".case__rampdot, .case__targetlab, .case__legend"), {
        autoAlpha: 0,
        duration: 0.6,
        ease: "power2.out",
        scrollTrigger: { trigger: el, start: "top 82%", once: true },
        delay: 0.7 + index * 0.05,
      });
    }, el);
    return () => ctx.revert();
  }, [reduce, index]);

  return (
    <motion.article
      ref={ref}
      className="case"
      onPointerMove={onMove}
      onPointerLeave={reset}
      style={
        reduce
          ? undefined
          : { rotateX: rx, rotateY: ry, transformPerspective: 1100 }
      }
      initial={reduce ? { opacity: 1 } : { opacity: 0, y: 44, filter: "blur(4px)" }}
      whileInView={{ opacity: 1, y: 0, filter: "blur(0px)" }}
      whileTap={reduce ? undefined : { scale: 0.985 }}
      viewport={{ once: true, margin: "0px 0px -12% 0px" }}
      transition={{ duration: 0.85, delay: index * 0.08, ease: EASE_OUT }}
    >
      <div
        className="case__inner"
        style={{ ["--case-accent" as string]: data.accent }}
      >
        {/* sector photo — leads the card, parallax/scale on hover */}
        <div className="case__photo">
          <motion.div
            className="case__photo-inner"
            style={reduce ? undefined : { x: imgX, y: imgY }}
          >
            <Image
              src={data.image}
              alt={data.alt}
              width={900}
              height={672}
              sizes="(max-width: 980px) 90vw, 30vw"
              loading="lazy"
              className="case__img"
            />
          </motion.div>
          <span className="case__photo-tag">{data.tag}</span>
          <span className="case__photo-no" aria-hidden="true">
            {String(index + 1).padStart(2, "0")}
          </span>
        </div>

        {/* per-case data visual */}
        <div className="case__viz" aria-hidden="true">
          <CaseViz data={data} />
        </div>

        <div className="case__body">
          <p className="case__problem">
            <span className="case__k">Before</span>
            {data.problem}
          </p>
          <p className="case__result display">{data.result}</p>
          <p className="case__how">{data.how}</p>
        </div>

        <div className="case__metric">
          <span className="case__metric-num display">{data.metricNum}</span>
          <span className="case__metric-lab">{data.metricLabel}</span>
        </div>
      </div>
    </motion.article>
  );
}
