"use client";

import { useEffect, useState } from "react";
import { grantFundingCycle } from "@/content/grants";
import { cn } from "@/lib/utils";

type Figure = (typeof grantFundingCycle)[number];

type Props = {
  figures?: readonly Figure[];
  intervalMs?: number;
  className?: string;
  valueClassName?: string;
  showCaption?: boolean;
  captionClassName?: string;
};

export function CyclingGrantAmount({
  figures = grantFundingCycle,
  intervalMs = 3200,
  className,
  valueClassName,
  showCaption = false,
  captionClassName,
}: Props) {
  const [index, setIndex] = useState(0);
  const [visible, setVisible] = useState(true);

  useEffect(() => {
    let swapTimer: ReturnType<typeof setTimeout>;
    const tick = setInterval(() => {
      setVisible(false);
      swapTimer = setTimeout(() => {
        setIndex((i) => (i + 1) % figures.length);
        setVisible(true);
      }, 220);
    }, intervalMs);

    return () => {
      clearInterval(tick);
      clearTimeout(swapTimer);
    };
  }, [figures.length, intervalMs]);

  const current = figures[index];

  return (
    <span className={cn("inline-flex flex-col items-center", className)}>
      <span
        className={cn(
          "inline-block transition-all duration-200",
          visible ? "translate-y-0 opacity-100" : "-translate-y-2 opacity-0",
          valueClassName
        )}
        aria-live="polite"
        aria-atomic="true"
      >
        <span className="sr-only">{current.label}: </span>
        {current.display}
      </span>
      {showCaption && (
        <span
          className={cn(
            "mt-1 text-xs font-normal normal-case tracking-normal text-muted-foreground transition-opacity duration-200",
            visible ? "opacity-100" : "opacity-0",
            captionClassName
          )}
        >
          {current.label}
        </span>
      )}
    </span>
  );
}
