import { useEffect, useRef, useState, useCallback } from 'react'
import { MessageBubble } from './MessageBubble'
import type { ChatMessage } from '../../types/protocol'
import { Sparkles, ArrowDown, ArrowUp } from 'lucide-react'

interface MessageListProps {
  messages: ChatMessage[]
  onNavigateToSubAgent?: (taskId: string, description: string) => void
}

export function MessageList({ messages, onNavigateToSubAgent }: MessageListProps) {
  const bottomRef = useRef<HTMLDivElement>(null)
  const containerRef = useRef<HTMLDivElement>(null)
  const isStickyRef = useRef(true)
  const prevShowBottomRef = useRef(false)
  const prevShowTopRef = useRef(false)
  const lastMessageCountRef = useRef(0)
  const prevMessageCountRef = useRef(0)
  const stickyLockUntilRef = useRef(0)
  const isProgrammaticScrollRef = useRef(false)
  const scrollTimerRef = useRef<number>(0)

  const [showScrollToBottom, setShowScrollToBottom] = useState(false)
  const [showScrollToTop, setShowScrollToTop] = useState(false)
  const [hasNewMessage, setHasNewMessage] = useState(false)

  // ---- scroll handlers ----

  const handleScroll = useCallback(() => {
    const el = containerRef.current
    if (!el) return

    // sticky lock 期间：防止中间 DOM 状态的 scroll 事件打断历史加载
    if (Date.now() < stickyLockUntilRef.current) {
      isStickyRef.current = true
      return
    }

    const distanceFromBottom = el.scrollHeight - el.scrollTop - el.clientHeight
    const nearBottom = distanceFromBottom < 120

    isStickyRef.current = nearBottom

    // 编程式滚动进行中（按钮点击触发），跳过按钮状态更新，避免闪烁
    if (isProgrammaticScrollRef.current) return

    // 回到顶部按钮：滚过 0.8 个视口时显示
    const shouldShowTop = el.scrollTop > el.clientHeight * 0.8
    if (shouldShowTop !== prevShowTopRef.current) {
      prevShowTopRef.current = shouldShowTop
      setShowScrollToTop(shouldShowTop)
    }

    // 回到底部按钮：离开底部时显示
    const shouldShowBottom = !nearBottom
    if (shouldShowBottom !== prevShowBottomRef.current) {
      prevShowBottomRef.current = shouldShowBottom
      setShowScrollToBottom(shouldShowBottom)
    }

    // 用户手动滚回底部时清除"有新消息"标记
    if (nearBottom && hasNewMessage) {
      setHasNewMessage(false)
    }
  }, [hasNewMessage])

  const scrollToBottom = useCallback((behavior: ScrollBehavior = 'smooth') => {
    isStickyRef.current = true
    prevShowBottomRef.current = false
    setShowScrollToBottom(false)
    setHasNewMessage(false)
    isProgrammaticScrollRef.current = true
    clearTimeout(scrollTimerRef.current)
    scrollTimerRef.current = setTimeout(() => {
      isProgrammaticScrollRef.current = false
    }, 500)
    bottomRef.current?.scrollIntoView({ behavior })
  }, [])

  const scrollToTop = useCallback(() => {
    isProgrammaticScrollRef.current = true
    clearTimeout(scrollTimerRef.current)
    scrollTimerRef.current = setTimeout(() => {
      isProgrammaticScrollRef.current = false
    }, 500)
    containerRef.current?.scrollTo({ top: 0, behavior: 'smooth' })
  }, [])

  // ---- auto-scroll effect ----

  useEffect(() => {
    // 消息清空 → 重置所有追踪状态（话题/会话切换）
    if (messages.length === 0) {
      prevMessageCountRef.current = 0
      lastMessageCountRef.current = 0
      isStickyRef.current = true
      return
    }

    const lastMessage = messages[messages.length - 1]
    const isFreshLoad = prevMessageCountRef.current === 0 && messages.length > 0

    // 用户自己发的消息 → 始终滚到底部
    if (lastMessage.role === 'user') {
      scrollToBottom('instant')
      prevMessageCountRef.current = messages.length
      return
    }

    // 新加载（话题切换后首次收到消息）→ 强制滚到底部
    if (isFreshLoad) {
      isStickyRef.current = true
      lastMessageCountRef.current = 0
      stickyLockUntilRef.current = Date.now() + 1500
      scrollToBottom('instant')
      prevMessageCountRef.current = messages.length
      return
    }

    // 用户在底部 → 自动跟随新消息
    if (isStickyRef.current && bottomRef.current) {
      bottomRef.current.scrollIntoView({ behavior: 'instant' })
    }

    // 用户不在底部且有新消息 → 标记未读
    if (!isStickyRef.current && messages.length > lastMessageCountRef.current) {
      setHasNewMessage(true)
    }

    lastMessageCountRef.current = messages.length
    prevMessageCountRef.current = messages.length
  }, [messages, scrollToBottom])

  // ---- ResizeObserver: 窗口大小变化时保持底部对齐 ----

  useEffect(() => {
    const el = containerRef.current
    if (!el) return

    const observer = new ResizeObserver(() => {
      if (isStickyRef.current && bottomRef.current) {
        bottomRef.current.scrollIntoView({ behavior: 'instant' })
      }
    })
    observer.observe(el)
    return () => observer.disconnect()
  }, [])

  // ---- 组件挂载时滚动到底部 ----

  useEffect(() => {
    if (messages.length > 0) {
      scrollToBottom('instant')
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [])

  // ---- 清理定时器 ----

  useEffect(() => {
    return () => clearTimeout(scrollTimerRef.current)
  }, [])

  // ---- empty state ----

  if (messages.length === 0) {
    return (
      <div className="flex h-full items-center justify-center">
        <div className="text-center animate-fade-in">
          <div className="mb-6 inline-flex h-20 w-20 items-center justify-center rounded-full bg-gradient-to-br from-[var(--accent-cyan)]/20 to-[var(--accent-blue)]/20 shadow-2xl shadow-[var(--accent-cyan)]/20">
            <Sparkles className="h-10 w-10 text-[var(--accent-cyan)]" />
          </div>
          <h2 className="mb-2 text-2xl font-bold text-[var(--text-primary)]">开始新的对话</h2>
          <p className="text-[var(--text-muted)]">在下方输入消息开始与 AI 助手聊天</p>
          <div className="mt-8 flex items-center justify-center gap-4 text-sm text-[var(--text-muted)]">
            <span className="px-3 py-1 rounded-full bg-[var(--bg-hover)] border border-[var(--border-color)]">/new 创建话题</span>
            <span className="px-3 py-1 rounded-full bg-[var(--bg-hover)] border border-[var(--border-color)]">/list 查看列表</span>
          </div>
        </div>
      </div>
    )
  }

  // ---- main render ----

  return (
    <div className="relative h-full">
      <div
        ref={containerRef}
        onScroll={handleScroll}
        className="h-full overflow-y-auto p-6 space-y-6 scroll-smooth"
      >
        {messages.map((message) => (
          <MessageBubble key={message.id} message={message} onNavigateToSubAgent={onNavigateToSubAgent} />
        ))}
        <div ref={bottomRef} />
      </div>

      {/* 浮动导航按钮组 */}
      <div className="absolute right-4 bottom-4 z-10 flex flex-col items-center gap-2 pointer-events-none">
        {/* 回到顶部 */}
        {showScrollToTop && (
          <button
            onClick={scrollToTop}
            className="pointer-events-auto group relative flex items-center justify-center
                       w-9 h-9 rounded-full
                       bg-[var(--bg-tertiary)]/80 backdrop-blur-md
                       border border-[var(--border-color)]
                       text-[var(--text-muted)] hover:text-[var(--accent-cyan)]
                       hover:border-[var(--accent-cyan)]/30
                       hover:shadow-[0_0_20px_var(--shadow-glow-sm)]
                       transition-all duration-300 ease-out
                       animate-fade-in"
            aria-label="回到顶部"
          >
            <ArrowUp className="h-4 w-4 transition-transform duration-300 group-hover:-translate-y-0.5" />
          </button>
        )}

        {/* 回到底部 */}
        {showScrollToBottom && (
          <button
            onClick={() => scrollToBottom('smooth')}
            className="pointer-events-auto group relative flex items-center justify-center
                       w-9 h-9 rounded-full
                       bg-[var(--bg-tertiary)]/80 backdrop-blur-md
                       border border-[var(--border-color)]
                       text-[var(--text-muted)] hover:text-[var(--accent-cyan)]
                       hover:border-[var(--accent-cyan)]/30
                       hover:shadow-[0_0_20px_var(--shadow-glow-sm)]
                       transition-all duration-300 ease-out
                       animate-fade-in"
            aria-label="回到底部"
          >
            <ArrowDown className={`h-4 w-4 transition-transform duration-300 group-hover:translate-y-0.5 ${hasNewMessage ? 'animate-bounce' : ''}`} />

            {/* 未读消息指示点 */}
            {hasNewMessage && (
              <span className="absolute -top-0.5 -right-0.5 flex h-2.5 w-2.5">
                <span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-[var(--accent-cyan)]/60"></span>
                <span className="relative inline-flex h-2.5 w-2.5 rounded-full bg-[var(--accent-cyan)]"></span>
              </span>
            )}
          </button>
        )}
      </div>
    </div>
  )
}
