"use client";

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

interface UseStickyOptions {
  /**
   * 粘性触发的偏移量（相对于容器顶部）
   * 默认为 0
   */
  offset?: number;
  /**
   * 抖动防护的滞后容差（像素）。
   * 会将触发边界向下偏移，避免 0 边界来回切换。
   * 默认为 2
   */
  hysteresis?: number;
  /**
   * 根元素，用于观察交叉状态
   * 默认为 null（使用视口）
   */
  root?: Element | null;
}

/**
 * 检测元素是否处于 sticky 状态的 hook
 * 
 * @param options 配置选项
 * @returns [ref, isSticky] - 需要绑定到目标元素的 ref 和 sticky 状态
 */
export function useSticky<T extends HTMLElement = HTMLDivElement>(
  options: UseStickyOptions = {}
): [RefObject<T | null>, boolean] {
  const { offset = 0, hysteresis = 2, root = null } = options;
  const elementRef = useRef<T>(null);
  const [isSticky, setIsSticky] = useState(false);
  const rafIdRef = useRef<number | null>(null);

  useEffect(() => {
    const element = elementRef.current;
    if (!element) return;

    // 如果没有指定 root，尝试自动查找滚动容器
    let scrollContainer = root;
    if (!scrollContainer) {
      // 查找具有 overflow 属性的父容器或 main-content 容器
      scrollContainer = document.getElementById('main-content') || null;
    }

    // 创建一个哨兵元素来检测 sticky 状态
    const sentinel = document.createElement('div');
    sentinel.style.position = 'relative';
    sentinel.style.top = `${offset}px`; // 设置与 sticky offset 相同的位置
    sentinel.style.left = '0';
    sentinel.style.width = '1px';
    sentinel.style.height = '1px';
    sentinel.style.pointerEvents = 'none';
    sentinel.style.visibility = 'hidden';
    
    // 将哨兵元素插入到目标元素之前
    element.parentNode?.insertBefore(sentinel, element);

    const observer = new IntersectionObserver(
      ([entry]) => {
        // 使用 rAF 合并更新，避免高频切换
        if (rafIdRef.current !== null) {
          cancelAnimationFrame(rafIdRef.current);
        }
        rafIdRef.current = requestAnimationFrame(() => {
          // 获取滚动容器的滚动位置
          const container = scrollContainer as HTMLElement;
          const scrollTop = container ? container.scrollTop : window.scrollY;
          
          // 获取元素相对于容器的位置
          const elementRect = element.getBoundingClientRect();
          const containerRect = container ? container.getBoundingClientRect() : { top: 0 };
          
          // 计算元素相对于容器顶部的距离
          const elementTopRelativeToContainer = elementRect.top - containerRect.top;
          
          // 只有当元素顶部到达或超过 offset 位置，并且哨兵不可见时，才认为是 sticky
          // 同时确保滚动位置大于元素初始位置
          const nextIsSticky = !entry.isIntersecting && 
                               elementTopRelativeToContainer <= offset + hysteresis &&
                               scrollTop > 0;
          
          // 仅在状态变化时更新，减少重复渲染
          setIsSticky(prev => (prev !== nextIsSticky ? nextIsSticky : prev));
        });
      },
      {
        root: scrollContainer,
        // 在向下滚动触发点加入滞后容差，远离 0 边界，减少抖动
        rootMargin: `-${offset + Math.max(0, Math.floor(hysteresis))}px 0px 0px 0px`,
        threshold: 0
      }
    );

    observer.observe(sentinel);

    return () => {
      observer.disconnect();
      sentinel.remove();
      if (rafIdRef.current !== null) {
        cancelAnimationFrame(rafIdRef.current);
        rafIdRef.current = null;
      }
    };
  }, [offset, hysteresis, root]);

  return [elementRef, isSticky];
}

/**
 * 简化版本的 useSticky hook，使用默认配置
 */
export function useStickySimple<T extends HTMLElement = HTMLDivElement>(): [RefObject<T | null>, boolean] {
  return useSticky<T>();
}
