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

/**
 * PortUtils 父子项动画 Hook（港口工具栏）
 *
 * 功能说明：
 * 1. 实现父级和子级的复杂交互动画序列
 * 2. 支持点击父级展开/收起子级，展现流畅的动画效果
 * 3. 初始化时不执行动画，首次点击后执行完整的展开/收起动画序列
 * 4. 使用依次动画（stagger）和并行动画，营造层次感
 *
 * 动画流程详解：
 *
 * 【初始显示】
 * - 使用 BottomUtils 声明式主容器动画
 * - 不执行父级的依次显示动画，保持静止
 *
 * 【展开动画序列】（点击父级展开子级）
 * 1. 所有父级依次下落隐藏（stagger：0.05s 间隔）
 *    - y: 0 → 30（向下移动）
 *    - opacity: 1 → 0（淡出）
 *    - x: 0（重置水平位置）
 *    - 单个动画时长：0.1s
 * 2. 选中的父级单独显示回来
 *    - y: 30 → 0（回到原位）
 *    - opacity: 0 → 1（淡入）
 *    - x: 0（保持水平位置）
 *    - 动画时长：0.1s
 * 3. 选中的父级移动到最左边
 *    - x: 0 → -offsetLeft（计算目标位置）
 *    - 缓动：easeInOut（平滑过渡）
 *    - 动画时长：0.1s
 * 4. 子级展开
 *    - opacity: 0 → 1（淡入）
 *    - 延迟：0.05s（等待步骤3完成）
 *    - 动画时长：0.1s
 *
 * 【收起动画序列】（点击父级收起子级）
 * 1. 子级收起
 *    - opacity: 1 → 0（淡出）
 *    - 动画时长：0.1s
 * 2. 所有父级在各自当前位置下落（并行执行）
 *    - y: 0 → 30（向下移动）
 *    - opacity: 1 → 0（淡出）
 *    - 保持各自的 x 位置（选中的在左边，其他在原位）
 *    - 动画时长：0.1s
 * 3. 所有父级回到原位（并行执行，仍在下方）
 *    - x: 当前位置 → 0（重置水平位置）
 *    - 动画时长：0.1s
 * 4. 所有父级依次从下向上显示（stagger：0.05s 间隔）
 *    - y: 30 → 0（回到原位）
 *    - opacity: 0 → 1（淡入）
 *    - x: 0（保持水平位置）
 *    - 单个动画时长：0.1s
 *
 * 动画配置：
 * - duration: 0.1s（单个动画的持续时间）
 * - staggerDelay: 0.05s（每个父级的延迟时间，用于依次动画）
 *
 * @param {number} parentCount - 父级数量
 * @param {number} currentIndex - 当前选中的父级索引（-1 表示未选中）
 * @param {boolean} isPortMode - 是否是港口模式
 * @returns {object} 返回包含以下属性的对象：
 *   - parentControls: 父级动画控制器数组，每个父级独立控制
 *   - childControls: 子级动画控制器，控制子级的展开/收起
 *   - optionRefs: 父级元素引用数组，用于计算位置偏移量
 *   - isAnimating: 是否正在执行动画，用于防止动画冲突
 *   - hasInteracted: 是否已经交互过，首次点击后才执行完整动画
 *   - shouldHideInactive: 是否应该隐藏非激活的父级，子级展开时隐藏其他父级
 *   - animationConfig: 动画配置对象（包含 duration 和 staggerDelay）
 */
export function usePortUtilsAnimation(parentCount, currentIndex, isPortMode) {
  // ==================== 动画配置 ====================
  const animationConfig = {
    duration: 0.1, // 单个动画的持续时间（秒）
    staggerDelay: 0.05, // 每个父级的延迟时间（秒），用于依次动画产生波浪效果
  };

  // ==================== 状态管理 ====================
  //
  // 动画时长说明：
  // - 单个动画：0.1s，非常快，营造敏捷的响应感
  // - stagger 延迟：0.05s，相邻父级之间的时间间隔，产生波浪效果
  //
  // 并行 vs 依次：
  // - 并行动画：多个动画同时执行（如所有父级同时回到原位）
  // - 依次动画：动画按顺序执行（如父级依次下落，每个间隔 0.05s）
  // ====================

  // 标记是否正在执行动画
  // 作用：防止在动画执行过程中触发新的动画，避免动画冲突
  const [isAnimating, setIsAnimating] = useState(false);

  // 标记是否已经交互过
  // 作用：初始化时不执行动画，首次点击后设置为 true，之后才执行完整动画
  const [hasInteracted, setHasInteracted] = useState(false);

  // 标记是否应该隐藏非激活的父级
  // 作用：当子级展开时，隐藏未选中的父级，避免视觉干扰
  // 在动画执行期间设置为 false，让所有父级参与动画
  // 动画完成后设置为 true，隐藏未选中的父级
  const [shouldHideInactive, setShouldHideInactive] = useState(false);

  // 父级元素的 ref 数组
  // 作用：获取父级 DOM 元素，用于计算位置偏移量（offsetLeft）
  const optionRefs = useRef([]);

  // 为每个父级创建独立的动画控制器
  // 作用：每个父级可以独立控制动画，实现依次动画效果
  const parentControls = Array.from({ length: parentCount }, () => useAnimation());

  // 子级的动画控制器
  // 作用：控制子级的展开/收起动画
  const childControls = useAnimation();

  // ==================== 初始化 ====================
  // 设置子级为初始状态（隐藏），确保一开始不可见
  useEffect(() => {
    childControls.set({ opacity: 0 });
  }, []);

  // ==================== 主题：展开/收起动画序列 ====================
  //
  // 展开动画（performExpandAnimation）：
  // 1. 所有父级依次下落隐藏（stagger 效果）
  // 2. 选中的父级单独显示回来
  // 3. 选中的父级移动到最左边
  // 4. 子级展开
  //
  // 收起动画（performCollapseAnimation）：
  // 1. 子级收起
  // 2. 所有父级在各自当前位置下落（并行）
  // 3. 所有父级回到原位（并行）
  // 4. 所有父级依次从下向上显示（stagger 效果）
  //
  // 使用 useCallback 缓存函数，避免不必要的重建
  // ====================

  // ==================== 展开动画序列 ====================
  const performExpandAnimation = useCallback(async () => {
    if (isAnimating)
      return;
    setIsAnimating(true);

    const { duration, staggerDelay } = animationConfig;
    const selectedIndex = currentIndex;

    // ===== 准备阶段 =====
    // 先设置为 false，让其他父级参与下落动画
    setShouldHideInactive(false);

    // ===== 步骤 1：所有父级依次下落隐藏 =====
    // 目的：让所有父级依次消失，为选中的父级腾出空间
    const hidePromises = parentControls.map((control, index) => {
      return control.start({
        y: 30, // 向下移动 30px
        opacity: 0, // 透明度变为 0
        x: 0, // 重置 x 位置到原始位置
        transition: { duration, delay: index * staggerDelay }, // 依次延迟，产生波浪效果
      });
    });

    await Promise.all(hidePromises); // 等待所有父级下落完成

    // ===== 步骤 2：选中的父级显示回来 =====
    // 目的：让选中的父级从下向上淡入显示
    await parentControls[selectedIndex].start({
      y: 0, // 回到原始 Y 位置
      opacity: 1, // 透明度变为 1
      x: 0, // 保持 x 为 0
      transition: { duration }, // 不延迟，立即执行
    });

    // ===== 步骤 3：选中的父级移动到最左边 =====
    // 目的：让选中的父级移动到容器最左侧，为子级展开腾出空间
    const selectedElement = optionRefs.current[selectedIndex];
    const targetX = -selectedElement.offsetLeft; // 计算目标 x 位置（负的偏移量）

    await parentControls[selectedIndex].start({
      x: targetX, // 移动到最左边
      transition: { duration, ease: "easeInOut" }, // 使用平滑的缓动函数
    });

    // ===== 步骤 4：子级展开 =====
    // 目的：让子级淡入显示
    await childControls.start({
      opacity: 1, // 透明度从 0 到 1
      transition: {
        duration, // 动画时长
        delay: staggerDelay, // 延迟执行，等待步骤 3 完成
      },
    });

    // ===== 动画完成 =====
    // 所有动画完成后，隐藏其他父级，避免干扰
    setShouldHideInactive(true);

    setIsAnimating(false);
  }, [isAnimating, currentIndex, parentControls, childControls, animationConfig]);

  // ==================== 首次交互监听 ====================
  // 监听 hasInteracted 变化，在第一次切换后执行动画
  useEffect(() => {
    if (hasInteracted && !isAnimating && currentIndex !== -1) {
      // 第一次切换到 motion.div 后，延迟一帧执行动画
      // 作用：确保 DOM 已更新，motion.div 已挂载
      requestAnimationFrame(() => {
        performExpandAnimation();
      });
    }
  }, [hasInteracted]);

  // ==================== 收起动画序列 ====================
  const performCollapseAnimation = useCallback(async () => {
    if (isAnimating)
      return;
    setIsAnimating(true);

    const { duration, staggerDelay } = animationConfig;

    // ===== 准备阶段 =====
    // 先设置为 false，让所有父级参与收起动画
    setShouldHideInactive(false);

    // ===== 步骤 1：子级收起 =====
    // 目的：先隐藏子级，避免视觉干扰
    await childControls.start({
      opacity: 0, // 透明度从 1 到 0
      transition: { duration }, // 立即执行
    });

    // ===== 步骤 2：所有父级在各自当前位置下落 =====
    // 目的：让所有父级从当前位置下落，保持各自的 x 位置
    const hidePromises = parentControls.map((control) => {
      return control.start({
        y: 30, // 向下移动 30px
        opacity: 0, // 透明度变为 0
        // 不设置 x，保持各自的当前位置（选中的父级在左边，其他在原位）
        transition: { duration },
      });
    });

    await Promise.all(hidePromises); // 等待所有父级下落完成

    // ===== 步骤 3：所有父级回到原位 =====
    // 目的：将所有父级的 x 位置重置为 0（仍在下方）
    await Promise.all(
      parentControls.map((control) => {
        return control.start({
          x: 0, // 重置 x 位置到原始位置
          transition: { duration }, // 平滑过渡
        });
      }),
    );

    // ===== 步骤 4：所有父级依次从下向上显示 =====
    // 目的：让所有父级依次从下向上淡入，恢复到初始状态
    const showPromises = parentControls.map((control, index) => {
      return control.start({
        y: 0, // 回到原始 Y 位置
        opacity: 1, // 透明度变为 1
        transition: { duration, delay: index * staggerDelay }, // 依次延迟，产生波浪效果
      });
    });

    await Promise.all(showPromises); // 等待所有父级显示完成

    // ===== 动画完成 =====
    // 收起完成，恢复隐藏状态
    setShouldHideInactive(true);

    setIsAnimating(false);
  }, [isAnimating, parentControls, childControls, animationConfig]);

  // ==================== 监听 currentIndex 变化，触发相应的动画 ====================
  useEffect(() => {
    // ===== 模式切换时重置交互状态 =====
    // 作用：当 isPortMode 变化时，重新设置成未交互过
    // 这样下次点击时不会触发动画，直到再次点击
    if (!isPortMode) {
      setHasInteracted(false);
    }
    if (!isPortMode || isAnimating)
      return;

    // ===== 判断当前是否有激活的父级 =====
    const hasActiveParent = currentIndex !== -1;

    // ===== 场景 1：有激活的父级，且是首次交互 =====
    if (hasActiveParent && !hasInteracted) {
      // 第一次点击：只设置 hasInteracted，不执行动画
      // 动画会在 hasInteracted 变化后的 useEffect 中执行
      // 作用：延迟动画执行，确保 DOM 已更新
      setHasInteracted(true);
    }
    // ===== 场景 2：有激活的父级，且已经交互过 =====
    else if (hasActiveParent && hasInteracted) {
      // 已经交互过，直接执行展开动画
      performExpandAnimation();
    }
    // ===== 场景 3：没有激活的父级，且已经交互过 =====
    else if (!hasActiveParent && hasInteracted) {
      // 只有在已经交互过的情况下，才执行收起动画
      // 作用：避免初始化时执行收起动画
      performCollapseAnimation();
    }
  }, [currentIndex, isPortMode]);

  // ==================== 返回值 ====================
  return {
    parentControls, // 父级动画控制器数组，每个父级独立控制
    childControls, // 子级动画控制器，控制子级的展开/收起
    optionRefs, // 父级元素引用数组，用于计算位置偏移量
    isAnimating, // 是否正在执行动画，用于防止动画冲突
    hasInteracted, // 是否已经交互过，首次点击后才执行完整动画
    shouldHideInactive, // 是否应该隐藏非激活的父级，子级展开时隐藏其他父级
    animationConfig, // 动画配置对象（包含 duration 和 staggerDelay）
  };
}
