import { useEffect, useLayoutEffect, useRef, useState } from 'react';
import type { ChatRow } from './turn-rows';

/**
 * A beat between your message landing and the previous turn folding away, so the two read as cause and
 * effect rather than as one simultaneous lurch. Short enough that it is a rhythm, not a wait.
 */
const HOLD_MS = 180;

/** Long enough to read as movement, short enough not to be a delay. `TurnFold` animates over the same span. */
export const COLLAPSE_MS = 260;

/** The fold that is closing right now: `open` is what it should be showing this frame. */
export type FoldExit = { key: string; open: boolean };

/**
 * Turn the fold into something you can watch happen.
 *
 * Folding is not a collapse — `buildRows` replaces a turn's work with a single summary row, so the rows you
 * were reading are gone on the same frame the summary arrives and there is nothing left to animate. The way
 * back is to let the new fold be *born open*, holding exactly the messages it replaced, and then close it:
 * the list keeps the same total height across the swap and the movement afterwards is a real height change.
 *
 * Only the newest fold, and only once. `enabled` is the same "have I watched a turn run here" question the
 * tool rows ask — opening an old conversation should render its folds closed, not play twenty animations at
 * you. Requiring the fold to be the *last* one keeps a prepend of older messages, which mints fold keys
 * above the ones already on screen, from being mistaken for a turn you just finished.
 */
export function useFoldExit(rows: ChatRow[], enabled: boolean): FoldExit | null {
  const [exit, setExit] = useState<FoldExit | null>(null);
  // null until the first pass, which is how "these folds were already here when I arrived" is told apart
  // from "this fold just appeared". Every fold on a freshly loaded transcript is new; none of them is recent.
  const knownFolds = useRef<ReadonlySet<string> | null>(null);

  useLayoutEffect(() => {
    const foldKeys = rows.filter((row) => row.kind === 'fold').map((row) => row.key);
    const known = knownFolds.current;
    knownFolds.current = new Set(foldKeys);
    if (!known || !enabled) return;

    const newest = foldKeys[foldKeys.length - 1];
    if (!newest || known.has(newest)) return;
    setExit({ key: newest, open: true });
  }, [rows, enabled]);

  useEffect(() => {
    if (!exit?.open) return;
    const timer = setTimeout(() => setExit((prev) => (prev ? { ...prev, open: false } : null)), HOLD_MS);
    return () => clearTimeout(timer);
  }, [exit]);

  useEffect(() => {
    if (!exit || exit.open) return;
    const timer = setTimeout(() => setExit(null), COLLAPSE_MS);
    return () => clearTimeout(timer);
  }, [exit]);

  return exit;
}
