import { useAnimation } from "motion/react";
import { useEffect, useRef, useState } from "react";

/**
 * Header 组件动画 Hook
 *
 * 功能说明：
 * 1. 监听标题内容变化
 * 2. 内容变化时执行上下方向的动画效果（向上离开 + 向下进入）
 * 3. 支持首次加载动画
 *
 * 动画效果：
 * - 进入动画：从上方 100px 处滑入，同时淡入（y: -100 → 0, opacity: 0 → 1）
 * - 离开动画：向上方 100px 处滑出，同时淡出（y: 0 → -100, opacity: 1 → 0）
 *
 * @param {string} currentTitle - 当前的标题内容
 * @returns {object} 返回包含以下属性的对象：
 *   - controls: motion 动画控制器
 *   - displayedTitle: 延迟显示的标题（用于动画过渡）
 */
export function useHeaderAnimation(currentTitle) {
  // ==================== 状态和引用管理 ====================

  // motion 动画控制器，用于控制 motion.header 的动画
  const controls = useAnimation();

  // 标记是否是首次渲染
  // 作用：首次渲染时需要特殊处理，确保初始状态正确设置
  const isFirstRender = useRef(true);

  // 延迟显示的标题状态
  // 作用：在标题切换时，先显示旧标题，动画完成后再更新为新标题
  // 这样确保离开动画显示的是旧标题，进入动画显示的是新标题
  const [displayedTitle, setDisplayedTitle] = useState(currentTitle);

  useEffect(() => {
    // ==================== 检查标题是否发生变化 ====================
    const titleChanged = displayedTitle !== currentTitle;

    // ==================== 首次渲染 ====================
    if (isFirstRender.current) {
      // ===== 步骤 1：设置元素到初始隐藏位置（上方外部）=====
      // - y: -100：元素位于视图上方 100px 处（隐藏）
      // - opacity: 0：完全透明
      // - controls.set() 是立即设置，不会触发动画过渡
      controls.set({
        y: -100, // Y 轴位置：从上方 100px 处开始
        opacity: 0, // 透明度：完全透明
      });

      // ===== 步骤 2：立即更新显示的标题 =====
      // 因为首次渲染不需要保留旧标题，直接设置为传入的标题
      setDisplayedTitle(currentTitle);

      // ===== 步骤 3：执行滑入动画（从上方滑入到正常位置）=====
      // - y: 0：从上方移动到正常位置
      // - opacity: 1：从透明变为不透明
      // - duration: 0.5s：动画时长 0.5 秒
      // - ease: "easeOut"：快速开始，缓慢结束的缓动函数
      controls.start({
        y: 0, // 移动到正常位置
        opacity: 1, // 淡入
        transition: { duration: 0.5, ease: "easeOut" },
      });

      // ===== 步骤 4：标记首次渲染完成 =====
      isFirstRender.current = false;
    }

    // ==================== 标题变化 ====================
    else if (titleChanged) {
      // ===== 步骤 1：先执行离开动画（向上离开）=====
      // 作用：显示旧标题向上滑出
      // - y: -100：向上移动到视图外部
      // - opacity: 0：同时淡出
      // - duration: 0.3s：较短的离开动画时长，显得更轻快
      // - ease: "easeIn"：缓慢开始，快速结束的缓动函数
      controls.start({
        y: -100, // 向上移动到外部
        opacity: 0, // 淡出
        transition: { duration: 0.3, ease: "easeIn" },
      }).then(() => {
        // ===== 步骤 2：离开动画完成后，更新显示的标题为新标题 =====
        // 此时旧标题已经完全离开视图，更新标题用户看不见
        setDisplayedTitle(currentTitle);

        // ===== 步骤 3：执行进入动画（从上方进入）=====
        // 作用：显示新标题从上方滑入
        // - y: 0：从上方移动到正常位置
        // - opacity: 1：从透明变为不透明
        // - duration: 0.5s：进入动画时长
        // - ease: "easeOut"：快速开始，缓慢结束的缓动函数
        controls.start({
          y: 0, // 从上方移动到正常位置
          opacity: 1, // 淡入
          transition: { duration: 0.5, ease: "easeOut" },
        });
      });
    }
  }, [currentTitle, controls, displayedTitle]);

  // ==================== 返回值 ====================
  // 返回动画控制器和延迟显示的标题
  return {
    controls, // motion 动画控制器，绑定到 motion.header 的 animate 属性
    displayedTitle, // 延迟显示的标题，用于在动画过渡期间保持视觉连续性
  };
}
