'use client';

import { type RefObject, useEffect, useRef } from 'react';

export interface UseChatHistoryOptions {
  enabled?: boolean;
  containerRef: RefObject<HTMLElement | null>;
  topSentinelRef: RefObject<HTMLElement | null>;
  hasMore: boolean;
  isLoadingMore: boolean;
  loadMore: () => Promise<void>;
}

/** Triggers `loadMore` when the top sentinel enters the container's viewport.
 *  Preserves scroll anchor: if the container's height grows after load, we
 *  bump scrollTop by the delta so the previously-visible message stays put. */
export function useChatHistory(options: UseChatHistoryOptions): void {
  const { enabled = true, containerRef, topSentinelRef, hasMore, isLoadingMore, loadMore } = options;
  const heightBeforeRef = useRef<number | null>(null);

  // Restore anchor after content prepends.
  useEffect(() => {
    if (heightBeforeRef.current == null) return;
    const el = containerRef.current;
    if (!el) {
      heightBeforeRef.current = null;
      return;
    }
    if (!isLoadingMore) {
      const delta = el.scrollHeight - heightBeforeRef.current;
      if (delta > 0) {
        el.scrollTop += delta;
      }
      heightBeforeRef.current = null;
    }
  }, [containerRef, isLoadingMore]);

  useEffect(() => {
    if (!enabled || !hasMore) return;
    const sentinel = topSentinelRef.current;
    const root = containerRef.current;
    if (!sentinel || !root) return;

    const observer = new IntersectionObserver(
      (entries) => {
        const entry = entries[0];
        if (!entry?.isIntersecting) return;
        if (isLoadingMore) return;
        const el = containerRef.current;
        if (el) heightBeforeRef.current = el.scrollHeight;
        void loadMore();
      },
      { root, threshold: 0, rootMargin: '200px 0px 0px 0px' },
    );

    observer.observe(sentinel);
    return () => observer.disconnect();
  }, [enabled, hasMore, isLoadingMore, containerRef, topSentinelRef, loadMore]);
}
