"use client";

import type { CSSProperties } from "react";
import { useEffect, useMemo, useRef, useState } from "react";
import type { ProcessStep } from "@/data/site-content";

type ProcessTimelineProps = {
  steps: ProcessStep[];
};

function clamp(value: number, min: number, max: number) {
  return Math.min(Math.max(value, min), max);
}

export function ProcessTimeline({ steps }: ProcessTimelineProps) {
  const sectionRef = useRef<HTMLDivElement | null>(null);
  const stepRefs = useRef<Array<HTMLDivElement | null>>([]);
  const [activeIndex, setActiveIndex] = useState(0);
  const [progress, setProgress] = useState(0);

  const markers = useMemo(() => steps.map((step) => step.step), [steps]);

  useEffect(() => {
    function updateTimeline() {
      const section = sectionRef.current;

      if (!section) {
        return;
      }

      const sectionRect = section.getBoundingClientRect();
      const viewportAnchor = window.innerHeight * 0.42;
      const rawProgress =
        (viewportAnchor - sectionRect.top) /
        Math.max(sectionRect.height - window.innerHeight * 0.3, 1);

      setProgress(clamp(rawProgress, 0, 1));

      let closestIndex = 0;
      let closestDistance = Number.POSITIVE_INFINITY;

      stepRefs.current.forEach((stepNode, index) => {
        if (!stepNode) {
          return;
        }

        const rect = stepNode.getBoundingClientRect();
        const center = rect.top + rect.height / 2;
        const distance = Math.abs(center - viewportAnchor);

        if (distance < closestDistance) {
          closestDistance = distance;
          closestIndex = index;
        }
      });

      setActiveIndex(closestIndex);
    }

    updateTimeline();

    let frame = 0;

    function onScrollOrResize() {
      cancelAnimationFrame(frame);
      frame = window.requestAnimationFrame(updateTimeline);
    }

    window.addEventListener("scroll", onScrollOrResize, { passive: true });
    window.addEventListener("resize", onScrollOrResize);

    return () => {
      cancelAnimationFrame(frame);
      window.removeEventListener("scroll", onScrollOrResize);
      window.removeEventListener("resize", onScrollOrResize);
    };
  }, []);

  return (
    <div
      ref={sectionRef}
      className="process-timeline"
      style={
        {
          "--timeline-progress": `${progress}`,
          "--timeline-step-count": `${steps.length}`,
        } as CSSProperties
      }
    >
      <div className="process-rail" aria-hidden="true">
        <div className="process-rail-track" />
        <div className="process-rail-fill" />
        <div className="process-rail-markers">
          {markers.map((marker, index) => (
            <span
              key={marker}
              className={`process-rail-marker ${
                index <= activeIndex ? "is-active" : ""
              }`}
            />
          ))}
        </div>
      </div>

      <div className="process-rows">
        {steps.map((step, index) => {
          const sideClass = index % 2 === 0 ? "is-right" : "is-left";
          const isActive = index <= activeIndex;

          return (
            <div
              key={step.step}
              ref={(node) => {
                stepRefs.current[index] = node;
              }}
              className={`process-row ${sideClass} ${
                isActive ? "is-active" : ""
              }`}
            >
              <div className="process-row-spacer" aria-hidden="true" />
              <div className="process-row-pin" aria-hidden="true" />
              <article className="process-step-card">
                <span className="process-step-number">{step.step}</span>
                <h3>{step.title}</h3>
                <p>{step.description}</p>
              </article>
            </div>
          );
        })}
      </div>
    </div>
  );
}
