"use client";

import { useEffect, useRef, useState } from "react";
import { usePostSettings } from "@/lib/site-context";

/**
 * A post's words, folded after a few lines.
 *
 * A long post used to push everything under it off the screen, so a feed
 * of three wordy posts was a feed of three posts. It shows the first few
 * lines and a "Read more"; how many lines is an admin setting, because
 * what reads as "a few" differs between a site of short notes and a site
 * of essays.
 *
 * The button only appears when there is actually something hidden. That
 * can't be known from the text — it depends on the column width and the
 * font — so it is measured after the browser has laid the paragraph out,
 * and re-measured when the window changes size.
 */
export function PostText({ text }: { text: string }) {
  const { linesBeforeMore } = usePostSettings();
  const limit = Number(linesBeforeMore ?? 4);

  const ref = useRef<HTMLParagraphElement | null>(null);
  const [open, setOpen] = useState(false);
  const [overflows, setOverflows] = useState(false);

  useEffect(() => {
    if (limit <= 0) return;
    const el = ref.current;
    if (!el) return;

    const measure = () => {
      // Only meaningful while it is clamped: once it is open the two
      // heights match and it would report there is nothing to hide.
      if (el.classList.contains("folded")) {
        setOverflows(el.scrollHeight - el.clientHeight > 1);
      }
    };

    measure();
    const ro = new ResizeObserver(measure);
    ro.observe(el);
    return () => ro.disconnect();
  }, [text, limit]);

  const folded = limit > 0 && !open;

  return (
    // The wrapper is what "Read more" is positioned against. It sits at the
    // end of the last visible line rather than on a line of its own, which
    // is where the eye already is when the text runs out.
    <span className="pc-textwrap">
      <p
        ref={ref}
        className={`pc-text${folded ? " folded" : ""}`}
        style={folded ? ({ ["--pc-lines" as string]: limit }) : undefined}
      >
        {text}
      </p>
      {folded && overflows && (
        <button onClick={() => setOpen(true)} className="pc-more">
          Read more
        </button>
      )}
    </span>
  );
}
