"use client";

import gsap from "gsap";
import { useId, useLayoutEffect, useMemo, useRef } from "react";

type Props = {
  series: number[];
  color: string;
  className?: string;
  delay?: number;
};

const W = 280;
const H = 64;

export function Sparkline({ series, color, className, delay = 0.7 }: Props) {
  const uid = useId().replace(/[^a-zA-Z0-9]/g, "");
  const pathRef = useRef<SVGPathElement>(null);
  const areaRef = useRef<SVGPathElement>(null);

  const { linePath, areaPath } = useMemo(() => {
    if (!series.length) return { linePath: "", areaPath: "" };
    const max = Math.max(1, ...series);
    const min = Math.min(...series);
    const range = Math.max(1, max - min);
    const step = series.length > 1 ? W / (series.length - 1) : W;
    const usable = H * 0.7;
    const baselineY = H - 4;

    const pts = series.map((v, i) => ({
      x: i * step,
      y: baselineY - ((v - min) / range) * usable,
    }));

    const line = pts
      .map(
        (p, i) =>
          `${i === 0 ? "M" : "L"} ${p.x.toFixed(1)} ${p.y.toFixed(1)}`,
      )
      .join(" ");

    const area = `${line} L ${pts[pts.length - 1].x.toFixed(1)} ${H} L 0 ${H} Z`;
    return { linePath: line, areaPath: area };
  }, [series]);

  useLayoutEffect(() => {
    const reduced =
      typeof window !== "undefined" &&
      window.matchMedia("(prefers-reduced-motion: reduce)").matches;
    if (reduced || !pathRef.current) return;

    const length = pathRef.current.getTotalLength();
    const ctx = gsap.context(() => {
      gsap.fromTo(
        pathRef.current,
        { strokeDasharray: length, strokeDashoffset: length },
        {
          strokeDashoffset: 0,
          duration: 1.6,
          ease: "power2.inOut",
          delay,
        },
      );
      if (areaRef.current) {
        gsap.fromTo(
          areaRef.current,
          { opacity: 0 },
          { opacity: 1, duration: 0.8, delay: delay + 0.3, ease: "power2.out" },
        );
      }
    });
    return () => ctx.revert();
  }, [linePath, delay]);

  if (!linePath) return null;

  const fillId = `sparkfill-${uid}`;
  const strokeId = `sparkline-${uid}`;

  return (
    <svg
      viewBox={`0 0 ${W} ${H}`}
      preserveAspectRatio="none"
      className={className}
      aria-hidden
    >
      <defs>
        <linearGradient id={fillId} x1="0" x2="0" y1="0" y2="1">
          <stop offset="0%" stopColor={color} stopOpacity="0.35" />
          <stop offset="100%" stopColor={color} stopOpacity="0" />
        </linearGradient>
        <linearGradient id={strokeId} x1="0" x2="1" y1="0" y2="0">
          <stop offset="0%" stopColor={color} stopOpacity="0.6" />
          <stop offset="100%" stopColor={color} stopOpacity="1" />
        </linearGradient>
      </defs>
      <path ref={areaRef} d={areaPath} fill={`url(#${fillId})`} />
      <path
        ref={pathRef}
        d={linePath}
        fill="none"
        stroke={`url(#${strokeId})`}
        strokeWidth="2"
        strokeLinecap="round"
        strokeLinejoin="round"
        vectorEffect="non-scaling-stroke"
      />
    </svg>
  );
}
