//! 消息列表滚动控制 — 跟随/锁存/回底按钮
//!
//! 职责:悬浮底部按钮显隐、跟随意图锁存(isFollowingBottom)、
//! scrollToBottom 回底操作、onContentChange 内容变化滚动策略。
//!
//! 不涉及工具卡片折叠逻辑(父组件注入 onNearBottom 回调解耦)。

import { ref, nextTick, type Ref } from 'vue'

/** 底部阈值:距底部 <80px 视为"在底部" */
const NEAR_BOTTOM_PX = 80
/** 内容溢出阈值:scrollHeight - clientHeight >100px 认为内容溢出容器 */
const OVERFLOW_PX = 100

export function useMessageScroll(containerRef: Ref<HTMLDivElement | undefined>) {
  // 回到底部按钮：内容溢出且不在底部时显示
  const showBackToBottom = ref(false)

  // B-260618-24: 跟随意图锁存。点回到底部/滚到底/发新消息→true;用户上滑→false。
  const isFollowingBottom = ref(true)
  // 边沿检测:上一帧是否在底部(用于触发 onNearBottom 回调)
  let wasNearBottom = true

  /** 用户是否在底部附近(上滑查看历史时不强制拉回) */
  function isNearBottom(): boolean {
    const el = containerRef.value
    if (!el) return true
    return el.scrollHeight - el.scrollTop - el.clientHeight < NEAR_BOTTOM_PX
  }

  /** 刷新回到底部按钮状态 */
  function refreshBackToBottom(): void {
    const el = containerRef.value
    if (!el) { showBackToBottom.value = false; return }
    const overflow = el.scrollHeight - el.clientHeight > OVERFLOW_PX
    showBackToBottom.value = overflow && !isNearBottom()
  }

  /**
   * 滚动事件处理:刷新回底按钮 + 底部边沿检测触发回调。
   * @param onNearBottom 滚近底部时的回调(父组件传入,如收起工具卡片)
   */
  function onMessagesScroll(onNearBottom?: () => void): void {
    refreshBackToBottom()
    const near = isNearBottom()
    if (near && !wasNearBottom) {
      onNearBottom?.()
    }
    wasNearBottom = near
    isFollowingBottom.value = near
  }

  /** 滚动到容器底部 */
  function scrollToBottom(smooth = false): void {
    const el = containerRef.value
    if (!el) return
    isFollowingBottom.value = true // 显式回底 = 跟随意图
    el.scrollTo({
      top: el.scrollHeight,
      behavior: smooth ? 'smooth' : 'instant',
    })
    showBackToBottom.value = false
  }

  /** 消息/流式内容变化时:跟随意图则自动滚,否则只刷新回底按钮 */
  function onContentChange(): void {
    if (isFollowingBottom.value) {
      nextTick(scrollToBottom)
    } else {
      refreshBackToBottom()
    }
  }

  /** 显式标记跟随意图(发新消息/切换对话时调用) */
  function setFollowing(v: boolean): void {
    isFollowingBottom.value = v
  }

  return {
    showBackToBottom,
    isFollowingBottom,
    isNearBottom,
    refreshBackToBottom,
    onMessagesScroll,
    scrollToBottom,
    onContentChange,
    setFollowing,
  }
}
