"use client";

import { useLayoutEffect, useRef, type CSSProperties, type ReactNode } from "react";

interface FitTextProps {
  children: ReactNode;
  className?: string;
  style?: CSSProperties;
  /** Forwarded to the rendered heading - some per-workshop CSS targets it. */
  id?: string;
  /** Smallest font size (px) the text may shrink to. */
  minFontSize?: number;
}

/**
 * Heading whose font size steps down only when a single word is wider than
 * the box (e.g. "PROGRAMMIERUNG" in a narrow ribbon tag). Text that already
 * fits keeps the font size from CSS untouched, so short/English labels render
 * exactly as before. Normal word-wrapping still applies for multi-word text.
 */
export default function FitText({
  children,
  className,
  style,
  id,
  minFontSize = 12,
}: FitTextProps) {
  const ref = useRef<HTMLHeadingElement>(null);

  useLayoutEffect(() => {
    const el = ref.current;
    if (!el) return;

    const fit = () => {
      el.style.fontSize = "";
      let size = parseFloat(getComputedStyle(el).fontSize);
      if (!size) return;
      while (el.scrollWidth > el.clientWidth + 1 && size > minFontSize) {
        size -= 1;
        el.style.fontSize = `${size}px`;
      }
    };

    fit();
    // Re-fit once web fonts land (metrics change) and when the box resizes.
    document.fonts?.ready.then(fit).catch(() => {});
    let lastWidth = el.clientWidth;
    const ro = new ResizeObserver(() => {
      if (el.clientWidth !== lastWidth) {
        lastWidth = el.clientWidth;
        fit();
      }
    });
    ro.observe(el);
    return () => ro.disconnect();
  }, [children, minFontSize]);

  return (
    <h4 ref={ref} id={id} className={className} style={{ ...style, overflowWrap: "normal" }}>
      {children}
    </h4>
  );
}
