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

/**
 * 内容切换动画 Hook
 *
 * 功能说明：
 * 1. 管理内容面板的显示/隐藏状态
 * 2. 处理内容切换时的动画效果（离开 + 进入）
 * 3. 处理折叠/展开时的动画效果
 * 4. 处理纯地图模式下的动画效果
 *
 * 优先级：pureMap > 折叠状态 > 内容变化
 *
 * @param {object} currentContent - 当前要显示的内容状态（包含 currentPort、currentBranchOffice、bottomUtilsCurrentIndex 等）
 * @param {boolean} isCollapsed - 当前是否处于折叠状态
 * @param {string} side - 'left' 或 'right'，控制动画方向
 * @param {boolean} isPureMap - 是否为纯地图模式
 * @returns {object} 返回包含以下属性的对象：
 *   - controls: motion 动画控制器
 *   - displayedContent: 延迟显示的内容状态（用于动画过渡）
 *   - isVisible: 元素可见性状态
 *   - handleCollapse: 处理折叠/展开的函数
 */
export function useContentAnimation(currentContent, isCollapsed, side = "left", isPureMap = false) {
  // ==================== 状态管理 ====================

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

  // 标记是否是首次渲染（首次渲染不执行离开动画，直接进入）
  const isLeftFirstRender = useRef(true);

  // 标记当前是否正在执行动画（防止动画冲突）
  const isAnimating = useRef(false);

  // 延迟显示的内容状态
  // 作用：在内容切换时，先显示旧内容，动画完成后再更新为新内容
  const [displayedContent, setDisplayedContent] = useState(currentContent);

  // 元素可见性状态
  // false: 元素被隐藏（折叠或纯地图模式）
  // true: 元素可见（非折叠、非纯地图模式）
  const [isVisible, setIsVisible] = useState(true);

  // ==================== 辅助函数 ====================

  /**
   * 计算动画的初始位置
   * @returns {number} 初始 X 轴位移值（负数表示在左侧，正数表示在右侧）
   */
  const getInitialX = () => side === "left" ? -300 : 300;

  // ==================== 折叠/展开处理 ====================

  /**
   * 处理折叠按钮点击事件
   * @param {Function} setCollapseState - setState 函数，用于更新折叠状态
   */
  const handleCollapse = (setCollapseState) => {
    if (isCollapsed) {
      // ==================== 展开逻辑 ====================
      // 1. 先同步显示内容（确保显示最新的内容）
      setDisplayedContent(currentContent);

      // 2. 显示元素
      setIsVisible(true);

      // 3. 更新折叠状态
      setCollapseState(false);

      // 4. 执行进入动画
      // 使用 requestAnimationFrame 确保 DOM 更新后再设置初始状态
      requestAnimationFrame(() => {
        // 设置元素到初始隐藏位置（侧边外部）
        controls.set({
          x: getInitialX(),
          opacity: 0,
        });

        // 然后触发进入动画（从侧边滑入）
        requestAnimationFrame(() => {
          controls.start({
            x: 0, // 移动到正常位置
            opacity: 1, // 淡入
            transition: { duration: 0.5, ease: "easeOut" },
          });
        });
      });
    }
    else {
      // ==================== 折叠逻辑 ====================
      // 执行离开动画（滑到侧边并淡出）
      controls.start({
        x: getInitialX(), // 移动到侧边外部
        opacity: 0, // 淡出
        transition: { duration: 0.3, ease: "easeIn" },
      }).then(() => {
        // 动画完成后：
        // 1. 隐藏元素
        setIsVisible(false);

        // 2. 更新折叠状态为 true
        setCollapseState(true);
      });
    }
  };

  // ==================== 主题：监听状态变化并执行动画 ====================

  useEffect(() => {
    // ==================== 场景 1：纯地图模式（最高优先级）====================
    if (isPureMap) {
      // 如果元素当前可见，执行离开动画并隐藏
      if (isVisible) {
        controls.start({
          x: getInitialX(), // 滑到侧边
          opacity: 0, // 淡出
          transition: { duration: 0.3, ease: "easeIn" },
        }).then(() => {
          // 动画完成后隐藏元素
          setIsVisible(false);
        });
      }
      // 纯地图模式下，不执行任何后续逻辑
      return;
    }

    // ==================== 场景 2：折叠状态 ====================
    if (isCollapsed) {
      // 检查内容是否发生变化
      const contentChanged = Object.keys(currentContent).some(
        key => displayedContent[key] !== currentContent[key],
      );

      // 静默更新内容（不执行动画，保持数据同步）
      if (contentChanged) {
        setDisplayedContent(currentContent);
      }

      // 确保元素保持隐藏（防止异常情况导致的意外显示）
      if (isVisible) {
        setIsVisible(false);
      }

      // 折叠状态下，不执行任何动画逻辑
      return;
    }

    // ==================== 场景 3：正常模式（非折叠、非纯地图）====================

    // 检查内容是否真的变化了
    const contentChanged = Object.keys(currentContent).some(
      key => displayedContent[key] !== currentContent[key],
    );

    // ----- 情况 A：首次渲染 -----
    if (isLeftFirstRender.current) {
      // 1. 设置元素到初始隐藏位置（侧边外部）
      controls.set({
        x: getInitialX(),
        opacity: 0,
      });

      // 2. 立即更新显示的内容
      setDisplayedContent(currentContent);

      // 3. 执行滑入动画（从侧边滑入到正常位置）
      controls.start({
        x: 0, // 移动到正常位置
        opacity: 1, // 淡入
        transition: { duration: 0.5, ease: "easeOut" },
      });

      // 4. 标记首次渲染完成
      isLeftFirstRender.current = false;
    }

    // ----- 情况 B：内容变化（用户切换工具）-----
    else if (contentChanged && !isAnimating.current) {
      // 标记开始执行动画（防止动画冲突）
      isAnimating.current = true;

      // 1. 先执行离开动画（旧内容离开）
      controls.start({
        x: getInitialX(), // 滑到侧边
        opacity: 0, // 淡出
        transition: { duration: 0.3, ease: "easeIn" },
      }).then(() => {
        // 离开动画完成后：

        // 2. 更新显示的内容为新内容
        setDisplayedContent(currentContent);

        // 3. 标记动画完成
        isAnimating.current = false;

        // 4. 执行进入动画（新内容进入）
        controls.start({
          x: 0, // 从侧边滑入到正常位置
          opacity: 1, // 淡入
          transition: { duration: 0.5, ease: "easeOut" },
        });
      });
    }

    // ----- 情况 C：从隐藏状态切换回来（退出纯地图模式或展开）-----
    else if (!isVisible) {
      // 1. 显示元素
      setIsVisible(true);

      // 2. 更新显示的内容
      setDisplayedContent(currentContent);

      // 3. 执行进入动画
      requestAnimationFrame(() => {
        // 设置元素到初始隐藏位置
        controls.set({
          x: getInitialX(),
          opacity: 0,
        });

        // 然后触发进入动画
        requestAnimationFrame(() => {
          controls.start({
            x: 0, // 滑入到正常位置
            opacity: 1, // 淡入
            transition: { duration: 0.5, ease: "easeOut" },
          });
        });
      });
    }
  }, [currentContent, isCollapsed, isPureMap, controls, displayedContent, side, isVisible]);

  // ==================== 返回值 ====================

  return {
    controls, // motion 动画控制器
    displayedContent, // 延迟显示的内容（用于动画过渡）
    isVisible, // 元素可见性状态
    handleCollapse, // 折叠/展开处理函数
  };
}
