"use client";

import { LazyMotion, domAnimation, m, useMotionValueEvent, useReducedMotion, useScroll, useTransform } from "motion/react";
import { useEffect, useRef, useState } from "react";
import type { CircuitStage } from "@/content/types";
import { cn } from "@/lib/cn";

const CENTER = { x: 300, y: 282 };
const RADIUS = 200;

function nodePosition(index: number) {
  const angle = (-90 + index * 72) * (Math.PI / 180);
  return { x: CENTER.x + RADIUS * Math.cos(angle), y: CENTER.y + RADIUS * Math.sin(angle), cos: Math.cos(angle), sin: Math.sin(angle) };
}

interface GrowthSystemProps {
  stages: CircuitStage[];
  loopNote: string;
}

/**
 * The Revenue Circuit. A sticky radial diagram whose loop draws as the visitor scrolls
 * through the five stages; the active stage is tracked with an IntersectionObserver.
 */
export function GrowthSystem({ stages, loopNote }: GrowthSystemProps) {
  const [active, setActive] = useState(0);
  const [closed, setClosed] = useState(false);
  const stagesRef = useRef<HTMLDivElement>(null);
  const stageRefs = useRef<(HTMLElement | null)[]>([]);
  const reduceMotion = useReducedMotion();

  const { scrollYProgress } = useScroll({ target: stagesRef, offset: ["start 65%", "end 55%"] });
  const pathLength = useTransform(scrollYProgress, [0, 1], [0.015, 1]);
  const railScale = useTransform(scrollYProgress, [0, 1], [0, 1]);

  useMotionValueEvent(scrollYProgress, "change", (value) => setClosed(value > 0.985));

  useEffect(() => {
    const observer = new IntersectionObserver(
      (entries) => {
        for (const entry of entries) {
          if (!entry.isIntersecting) continue;
          const index = stageRefs.current.indexOf(entry.target as HTMLElement);
          if (index > -1) setActive(index);
        }
      },
      { rootMargin: "-45% 0px -45% 0px" },
    );
    stageRefs.current.forEach((element) => element && observer.observe(element));
    return () => observer.disconnect();
  }, []);

  const goToStage = (index: number) => {
    stageRefs.current[index]?.scrollIntoView({ behavior: reduceMotion ? "auto" : "smooth", block: "center" });
  };

  return (
    <LazyMotion features={domAnimation} strict>
      {/* Compact progress rail for small screens. */}
      <div className="sticky top-16 z-20 -mx-5 mt-12 border-y border-line bg-paper/95 px-5 py-3 lg:hidden">
        <ol className="flex justify-between gap-2">
          {stages.map((stage, index) => (
            <li key={stage.id}>
              <button
                type="button"
                onClick={() => goToStage(index)}
                aria-current={active === index ? "step" : undefined}
                className={cn(
                  "flex min-h-11 flex-col items-start justify-center text-left text-xs transition-colors",
                  active === index ? "text-ink" : "text-muted",
                )}
              >
                <span className="font-mono text-data">{stage.index}</span>
                <span className="font-medium">{stage.name}</span>
              </button>
            </li>
          ))}
        </ol>
        <div className="mt-2 h-px bg-line">
          <m.div className="h-px origin-left bg-signal" style={{ scaleX: railScale }} />
        </div>
      </div>

      <div className="mt-10 grid gap-10 lg:mt-20 lg:grid-cols-12 lg:gap-6">
        <div className="hidden lg:col-span-6 lg:block">
          <div className="sticky top-28">
            <svg viewBox="0 0 600 564" className="h-auto w-full" role="img" aria-labelledby="circuit-diagram-title">
              <title id="circuit-diagram-title">
                The Revenue Circuit: Discover, Acquire, Convert, Measure, and Expand, arranged as one closed loop around revenue.
              </title>
              <circle cx={CENTER.x} cy={CENTER.y} r={RADIUS} className="fill-none stroke-line" strokeWidth="1" />
              <m.circle
                cx={CENTER.x}
                cy={CENTER.y}
                r={RADIUS}
                className="fill-none stroke-signal"
                strokeWidth="2"
                transform={`rotate(-90 ${CENTER.x} ${CENTER.y})`}
                style={{ pathLength }}
              />

              {stages.map((stage, index) => {
                const { x, y } = nodePosition(index);
                return (
                  <line
                    key={`spoke-${stage.id}`}
                    x1={CENTER.x + (x - CENTER.x) * 0.36}
                    y1={CENTER.y + (y - CENTER.y) * 0.36}
                    x2={CENTER.x + (x - CENTER.x) * 0.9}
                    y2={CENTER.y + (y - CENTER.y) * 0.9}
                    className={cn("transition-colors duration-500", index === active ? "stroke-signal/50" : "stroke-ink/10")}
                    strokeDasharray="2 5"
                  />
                );
              })}

              <circle cx={CENTER.x} cy={CENTER.y} r="62" className="fill-surface stroke-line" />
              <text x={CENTER.x} y={CENTER.y - 6} textAnchor="middle" className={cn("font-mono transition-colors", closed ? "fill-signal" : "fill-muted")} fontSize="10" letterSpacing="0.1em">
                {closed ? "LOOP CLOSED" : "THE CIRCUIT"}
              </text>
              <text x={CENTER.x} y={CENTER.y + 18} textAnchor="middle" className="fill-ink" fontSize="22" fontWeight="500" letterSpacing="-0.02em">
                Revenue
              </text>

              {stages.map((stage, index) => {
                const { x, y, cos, sin } = nodePosition(index);
                const isActive = index === active;
                const isPast = index < active;
                const labelX = x + cos * 34;
                const labelY = y + sin * 34;
                const anchor = cos > 0.3 ? "start" : cos < -0.3 ? "end" : "middle";
                const nameY = index === 0 ? labelY - 4 : labelY + 14;
                const indexY = index === 0 ? labelY - 24 : labelY - 6;
                return (
                  <g
                    key={stage.id}
                    role="button"
                    tabIndex={0}
                    aria-label={`Go to stage ${stage.index}: ${stage.name}`}
                    className="cursor-pointer focus:outline-none [&:focus-visible>circle:first-child]:stroke-signal"
                    onClick={() => goToStage(index)}
                    onKeyDown={(event) => {
                      if (event.key === "Enter" || event.key === " ") {
                        event.preventDefault();
                        goToStage(index);
                      }
                    }}
                  >
                    <circle cx={x} cy={y} r="24" className={cn("transition-all duration-500", isActive ? "fill-signal/10 stroke-signal/30" : "fill-transparent stroke-transparent")} />
                    <circle
                      cx={x}
                      cy={y}
                      r={isActive ? 10 : 7.5}
                      className={cn(
                        "transition-all duration-500",
                        isActive ? "fill-signal stroke-signal" : isPast ? "fill-signal-mist stroke-signal" : "fill-surface stroke-ink",
                      )}
                      strokeWidth="1.5"
                    />
                    <text x={labelX} y={indexY} textAnchor={anchor} className={cn("font-mono transition-colors", isActive ? "fill-signal" : "fill-muted")} fontSize="11" letterSpacing="0.08em">
                      {stage.index}
                    </text>
                    <text x={labelX} y={nameY} textAnchor={anchor} className={cn("transition-colors", isActive ? "fill-ink" : "fill-ink-soft")} fontSize="19" fontWeight="500" letterSpacing="-0.01em">
                      {stage.name}
                    </text>
                  </g>
                );
              })}
            </svg>
            <p className="mt-2 flex items-center gap-2 text-sm text-muted">
              <span aria-hidden="true" className={cn("size-1.5 rounded-full transition-colors", closed ? "bg-signal" : "bg-line-strong")} />
              {loopNote}
            </p>
          </div>
        </div>

        <div ref={stagesRef} className="lg:col-span-6">
          {stages.map((stage, index) => (
            <article
              key={stage.id}
              id={`stage-${stage.id}`}
              ref={(element) => {
                stageRefs.current[index] = element;
              }}
              aria-labelledby={`stage-${stage.id}-title`}
              className={cn(
                "border-t border-line py-10 transition-opacity duration-500 lg:flex lg:min-h-[64vh] lg:flex-col lg:justify-center lg:py-16",
                index === 0 && "border-t-0 lg:pt-0",
                "circuit-stage",
              )}
              data-active={active === index}
            >
              <p className="flex items-center gap-3 text-label uppercase text-muted">
                <span className="font-mono text-signal">{stage.index}</span>
                <span aria-hidden="true" className="h-px w-8 bg-line-strong" />
                Stage
              </p>
              <h3 id={`stage-${stage.id}-title`} className="mt-4 text-display-md">
                {stage.name}
              </h3>
              <p className="mt-4 text-title text-ink">{stage.promise}</p>
              <p className="mt-4 max-w-xl text-ink-soft">{stage.description}</p>
              <ul className="mt-7 flex flex-wrap gap-2" aria-label={`${stage.name} activities`}>
                {stage.items.map((item) => (
                  <li key={item} className="rounded-sm border border-line bg-surface px-3 py-1.5 text-sm text-ink-soft">
                    {item}
                  </li>
                ))}
              </ul>
              <div className="mt-7 flex max-w-xl gap-4 border-t border-line pt-5">
                <span className="text-label uppercase text-muted">Output</span>
                <p className="text-[0.9375rem]">{stage.output}</p>
              </div>
            </article>
          ))}
        </div>
      </div>
    </LazyMotion>
  );
}
