import { useState, useEffect } from 'react'
import { User, Bot, Wrench, CheckCircle, AlertCircle, Terminal, File, Image, FileText, Music, Video, Download, ChevronDown, ChevronRight, Copy, Check, Loader2, XCircle, Clock, Loader, X, Brain, Maximize2 } from 'lucide-react'
import ReactMarkdown from 'react-markdown'
import remarkGfm from 'remark-gfm'
import type { ChatMessage, Attachment, TaskToolResult } from '../../types/protocol'
import { ToolDetailModal } from './ToolDetailModal'

// 状态图标组件
function StatusIcon({ status, size = 14 }: { status: 'calling' | 'result' | 'pending' | 'success' | 'failed' | 'timeout', size?: number }) {
  const iconClass = `transition-all duration-300`

  switch (status) {
    case 'calling':
      return (
        <Loader2
          className={`${iconClass} animate-spin`}
          style={{ width: size, height: size }}
          strokeWidth={2.5}
        />
      )
    case 'result':
    case 'success':
      return (
        <CheckCircle
          className={`${iconClass} animate-scale-in`}
          style={{ width: size, height: size }}
          strokeWidth={2.5}
        />
      )
    case 'failed':
      return (
        <XCircle
          className={`${iconClass} animate-scale-in`}
          style={{ width: size, height: size }}
          strokeWidth={2.5}
        />
      )
    case 'timeout':
      return (
        <Clock
          className={`${iconClass} animate-scale-in`}
          style={{ width: size, height: size }}
          strokeWidth={2.5}
        />
      )
    case 'pending':
      return (
        <Loader
          className={`${iconClass} animate-spin`}
          style={{ width: size, height: size }}
          strokeWidth={2.5}
        />
      )
    default:
      return null
  }
}

interface MessageBubbleProps {
  message: ChatMessage
  onNavigateToSubAgent?: (taskId: string, description: string, subagentType?: string) => void
  showThinking?: boolean
}

function getAttachmentIcon(mediaType: string) {
  switch (mediaType) {
    case 'image': return <Image className="h-4 w-4" />
    case 'audio': return <Music className="h-4 w-4" />
    case 'video': return <Video className="h-4 w-4" />
    case 'file': return <FileText className="h-4 w-4" />
    default: return <File className="h-4 w-4" />
  }
}

function getFileName(path: string): string {
  const parts = path.replace(/\\/g, '/').split('/')
  return parts[parts.length - 1] || path
}

function formatTime(timestamp: number) {
  return new Date(timestamp * 1000).toLocaleTimeString('zh-CN', {
    hour: '2-digit',
    minute: '2-digit',
  })
}

function formatDuration(ms: number): string {
  if (ms < 1000) {
    return `${ms}ms`
  }
  if (ms < 60000) {
    return `${(ms / 1000).toFixed(1)}s`
  }
  const minutes = Math.floor(ms / 60000)
  const seconds = Math.floor((ms % 60000) / 1000)
  return `${minutes}m ${seconds}s`
}

function AttachmentCard({ attachment }: { attachment: Attachment }) {
  const fileName = attachment.file_name || getFileName(attachment.path)

  const handleDownload = (e: React.MouseEvent) => {
    if (!attachment.content_base64) return

    e.preventDefault()
    const mimeType = attachment.mime_type || 'application/octet-stream'
    const byteChars = atob(attachment.content_base64)
    const byteNums = new Array(byteChars.length)
    for (let i = 0; i < byteChars.length; i++) {
      byteNums[i] = byteChars.charCodeAt(i)
    }
    const byteArr = new Uint8Array(byteNums)
    const blob = new Blob([byteArr], { type: mimeType })
    const url = URL.createObjectURL(blob)

    const a = document.createElement('a')
    a.href = url
    a.download = fileName
    document.body.appendChild(a)
    a.click()
    document.body.removeChild(a)
    URL.revokeObjectURL(url)
  }

  const canDownload = !!attachment.content_base64

  return (
    <div
      onClick={canDownload ? handleDownload : undefined}
      className={`flex items-center gap-2 rounded-lg bg-[var(--overlay-hover)] border border-[var(--border-color)] px-3 py-2 text-xs transition-colors group ${
        canDownload ? 'hover:bg-[var(--overlay-subtle)] hover:border-[var(--accent-cyan)]/30 cursor-pointer' : ''
      }`}
      title={canDownload ? `下载 ${fileName}` : attachment.path}
    >
      <span className={`text-[var(--text-secondary)] transition-colors ${canDownload ? 'group-hover:text-[var(--accent-cyan)]' : ''}`}>
        {getAttachmentIcon(attachment.media_type)}
      </span>
      <span className={`text-[var(--text-secondary)] truncate max-w-[200px] transition-colors ${canDownload ? 'group-hover:text-[var(--text-primary)]' : ''}`} title={attachment.path}>
        {fileName}
      </span>
      <span className="text-[var(--text-muted)] ml-auto shrink-0">{attachment.media_type}</span>
      {canDownload && (
        <Download className="h-3 w-3 text-[var(--text-muted)] group-hover:text-[var(--accent-cyan)] transition-colors" />
      )}
    </div>
  )
}

function ImageLightbox({ src, mimeType, fileName, onClose }: { src: string; mimeType: string; fileName?: string; onClose: () => void }) {
  useEffect(() => {
    const handleKeyDown = (e: KeyboardEvent) => {
      if (e.key === 'Escape') onClose()
    }
    document.addEventListener('keydown', handleKeyDown)
    return () => document.removeEventListener('keydown', handleKeyDown)
  }, [onClose])

  const handleDownload = (e: React.MouseEvent) => {
    e.stopPropagation()
    const byteChars = atob(src)
    const byteNums = new Array(byteChars.length)
    for (let i = 0; i < byteChars.length; i++) {
      byteNums[i] = byteChars.charCodeAt(i)
    }
    const byteArr = new Uint8Array(byteNums)
    const blob = new Blob([byteArr], { type: mimeType })
    const url = URL.createObjectURL(blob)
    const a = document.createElement('a')
    a.href = url
    a.download = fileName || `image.${mimeType.split('/')[1] || 'png'}`
    document.body.appendChild(a)
    a.click()
    document.body.removeChild(a)
    URL.revokeObjectURL(url)
  }

  return (
    <div
      className="fixed inset-0 z-50 flex items-center justify-center bg-black/85 backdrop-blur-sm animate-fade-in"
      onClick={onClose}
    >
      {/* 顶部工具栏 */}
      <div className="absolute top-4 right-4 flex items-center gap-2 z-10">
        <button
          onClick={handleDownload}
          className="p-2 rounded-full bg-white/10 hover:bg-white/20 text-white/80 hover:text-white transition-colors"
          aria-label="下载图片"
          title="下载图片"
        >
          <Download className="h-5 w-5" />
        </button>
        <button
          onClick={onClose}
          className="p-2 rounded-full bg-white/10 hover:bg-white/20 text-white/80 hover:text-white transition-colors"
          aria-label="关闭"
          title="关闭"
        >
          <X className="h-5 w-5" />
        </button>
      </div>
      <img
        src={`data:${mimeType};base64,${src}`}
        className="max-w-[90vw] max-h-[90vh] object-contain rounded-lg shadow-2xl"
        onClick={(e) => e.stopPropagation()}
        alt="图片预览"
      />
    </div>
  )
}

function CopyButton({ text, className = '' }: { text: string; className?: string }) {
  const [copied, setCopied] = useState(false)

  const handleCopy = (e: React.MouseEvent) => {
    e.stopPropagation()
    navigator.clipboard.writeText(text).then(() => {
      setCopied(true)
      setTimeout(() => setCopied(false), 1500)
    }).catch(() => {
      // fallback silently
    })
  }

  if (!text) return null

  return (
    <button
      onClick={handleCopy}
      className={`opacity-0 group-hover:opacity-100 transition-opacity p-0.5 rounded hover:bg-[var(--overlay-subtle)] flex-shrink-0 ${className}`}
      title="复制"
    >
      {copied ? (
        <Check className="h-3 w-3 text-emerald-400" />
      ) : (
        <Copy className="h-3 w-3 text-[var(--text-muted)]" />
      )}
    </button>
  )
}

function ThinkingSection({ content }: { content: string }) {
  const [expanded, setExpanded] = useState(false)

  return (
    <div className="rounded-lg border border-[var(--border-color)] bg-[var(--overlay-hover)] overflow-hidden">
      <button
        onClick={(e) => { e.stopPropagation(); setExpanded(!expanded) }}
        className="flex items-center gap-2 w-full px-3 py-2 text-xs text-[var(--text-muted)] hover:text-[var(--text-secondary)] hover:bg-[var(--overlay-subtle)] transition-colors cursor-pointer select-none"
      >
        <Brain className="h-3.5 w-3.5 text-[var(--accent-purple)] flex-shrink-0" />
        <span className="font-medium text-[var(--accent-purple)]">Thinking</span>
        {expanded ? (
          <ChevronDown className="h-3 w-3 ml-auto flex-shrink-0" />
        ) : (
          <ChevronRight className="h-3 w-3 ml-auto flex-shrink-0" />
        )}
        {!expanded && (
          <span className="text-[var(--text-muted)] truncate flex-1 text-left">
            {content.slice(0, 60)}{content.length > 60 ? '…' : ''}
          </span>
        )}
      </button>
      {expanded && (
        <div className="px-3 py-2 border-t border-[var(--border-color)] animate-thinking-reveal">
          <div className="text-xs text-[var(--text-secondary)] whitespace-pre-wrap leading-relaxed max-h-64 overflow-y-auto scrollbar-thin">
            {content}
          </div>
        </div>
      )}
    </div>
  )
}

function parseTaskResult(content: string): TaskToolResult | null {
  if (!content) return null
  try {
    const parsed = JSON.parse(content)
    if (
      parsed &&
      typeof parsed.status === 'string' &&
      typeof parsed.output === 'string' &&
      typeof parsed.summary === 'string' &&
      typeof parsed.task_id === 'string'
    ) {
      return parsed as TaskToolResult
    }
    return null
  } catch {
    return null
  }
}

export function MessageBubble({ message, onNavigateToSubAgent, showThinking = true }: MessageBubbleProps) {
  const isUser = message.role === 'user'
  const isTool = message.role === 'tool'
  const isMergedTool = message.type === 'merged_tool'
  const [toolExpanded, setToolExpanded] = useState(false)
  const [showDetailModal, setShowDetailModal] = useState(false)
  const [lightboxImage, setLightboxImage] = useState<{ base64: string; mimeType: string; fileName?: string } | null>(null)

  const lightboxElement = lightboxImage ? (
    <ImageLightbox
      src={lightboxImage.base64}
      mimeType={lightboxImage.mimeType}
      fileName={lightboxImage.fileName}
      onClose={() => setLightboxImage(null)}
    />
  ) : null

  if (isMergedTool) {
    const status = message.status || 'calling'
    const hasResult = !!(message.resultContent)
    const hasArgs = message.arguments !== undefined && message.arguments !== null

    const statusConfig = {
      calling: {
        dot: 'bg-amber-400 animate-pulse',
        fullBorder: 'border-amber-500/30',
        iconColor: 'text-amber-400',
        avatarBg: 'bg-amber-500/20',
        avatarIcon: 'text-amber-400',
      },
      result: {
        dot: 'bg-emerald-400',
        fullBorder: 'border-emerald-500/30',
        iconColor: 'text-emerald-400',
        avatarBg: 'bg-emerald-500/20',
        avatarIcon: 'text-emerald-400',
      },
      pending: {
        dot: 'bg-orange-400 animate-pulse',
        fullBorder: 'border-orange-500/30',
        iconColor: 'text-orange-400',
        avatarBg: 'bg-orange-500/20',
        avatarIcon: 'text-orange-400',
      },
    }[status]

    const formatJSON = (text: string): string => {
      try {
        return JSON.stringify(JSON.parse(text), null, 2)
      } catch {
        return text
      }
    }

    function stripToolResultPrefix(text: string): string {
      const lines = text.split('\n')
      if (lines[0]?.startsWith('工具结果')) {
        let start = 1
        while (start < lines.length && lines[start].trim() === '') {
          start++
        }
        return lines.slice(start).join('\n')
      }
      return text
    }

    const argsPreview = hasArgs
      ? JSON.stringify(message.arguments).slice(0, 500)
      : ''

    const displayContent = hasResult ? stripToolResultPrefix(message.resultContent!) : ''

    const isTaskTool = message.toolName === 'task'
    const taskResult = isTaskTool && hasResult ? parseTaskResult(displayContent) : null
    const subagentType = (message.arguments as Record<string, unknown> | null)?.subagent_type as string || 'general'
    const taskDescription = (message.arguments as Record<string, unknown> | null)?.description as string || ''
    const taskPrompt = (message.arguments as Record<string, unknown> | null)?.prompt as string || ''

    // task tool 专用的状态配色
    const taskStatusConfig = {
      success: { dot: 'bg-emerald-400', borderColor: 'border-emerald-500/40', iconColor: 'text-emerald-400' },
      failed: { dot: 'bg-red-400', borderColor: 'border-red-500/40', iconColor: 'text-red-400' },
      timeout: { dot: 'bg-amber-400', borderColor: 'border-amber-500/40', iconColor: 'text-amber-400' },
    } as const

    return (
      <div className="flex gap-3 animate-slide-in">
        <div className={`flex h-7 w-7 shrink-0 items-center justify-center rounded-full mt-0.5 ${
          isTaskTool ? 'bg-violet-500/20' : statusConfig.avatarBg
        }`}>
          {isTaskTool ? (
            <Bot className="h-3.5 w-3.5 text-violet-400" />
          ) : (
            <Terminal className={`h-3.5 w-3.5 ${statusConfig.avatarIcon}`} />
          )}
        </div>
        <div className="max-w-[80%] min-w-0">
          <div className="flex items-center gap-2 mb-1">
            <span className="text-xs font-medium text-[var(--text-secondary)]">{message.toolName || 'Tool'}</span>
            {isTaskTool && (
              <span className="text-xs px-1.5 py-0.5 rounded bg-violet-500/10 text-violet-400">
                子智能体·{subagentType}
              </span>
            )}
            <span className="text-xs text-[var(--text-muted)]">{formatTime(message.timestamp)}</span>
          </div>
          <div
            onClick={() => setToolExpanded(!toolExpanded)}
            className={`cursor-pointer rounded-xl border bg-[var(--bg-tertiary)]/60 w-full transition-all duration-500 hover:bg-[var(--bg-tertiary)]/80 group ${
              taskResult ? taskStatusConfig[taskResult.status].borderColor : statusConfig.fullBorder
            }`}
          >
            {/* Header row */}
            <div className="flex items-center gap-2 px-3 py-2">
              <span className={`inline-block h-2 w-2 rounded-full flex-shrink-0 transition-colors duration-500 ${
                taskResult ? taskStatusConfig[taskResult.status].dot : statusConfig.dot
              }`} />
              <span className="text-sm font-medium text-[var(--text-secondary)] truncate">
                {isTaskTool ? (taskDescription || '子智能体任务') : (message.toolName || 'Tool')}
              </span>
              <span className={`flex-shrink-0 transition-all duration-300 ${
                taskResult ? taskStatusConfig[taskResult.status].iconColor : statusConfig.iconColor
              }`}>
                {taskResult ? (
                  <StatusIcon status={taskResult.status} />
                ) : (
                  <StatusIcon status={status} />
                )}
              </span>
              {status === 'result' && message.durationMs != null && (
                <span className="text-xs text-[var(--text-muted)] flex-shrink-0 tabular-nums ml-1">
                  ⏱️ {formatDuration(message.durationMs)}
                </span>
              )}
              {hasResult && <CopyButton text={taskResult ? taskResult.output : displayContent} />}
              <button
                onClick={(e) => { e.stopPropagation(); setShowDetailModal(true) }}
                className="opacity-0 group-hover:opacity-100 transition-opacity p-0.5 rounded hover:bg-[var(--overlay-subtle)] flex-shrink-0"
                title="放大查看"
              >
                <Maximize2 className="h-3 w-3 text-[var(--text-muted)]" />
              </button>
              <span className="ml-auto flex-shrink-0">
                {toolExpanded ? (
                  <ChevronDown className="h-3.5 w-3.5 text-[var(--text-muted)]" />
                ) : (
                  <ChevronRight className="h-3.5 w-3.5 text-[var(--text-muted)]" />
                )}
              </span>
            </div>

            {/* 模型思考内容（工具调用时展示） */}
            {showThinking && message.reasoningContent && !toolExpanded && (
              <div className="px-3 pb-1 mb-2">
                <ThinkingSection content={message.reasoningContent} />
              </div>
            )}
            {/* Collapsed preview */}
            {!toolExpanded && (
              <>
                {hasArgs && argsPreview && !taskResult && (
                  <div className="px-3 pb-1 text-xs text-[var(--text-muted)] font-mono line-clamp-3"
                       style={{
                         display: '-webkit-box',
                         WebkitLineClamp: 3,
                         WebkitBoxOrient: 'vertical',
                         overflow: 'hidden',
                       }}>
                    {argsPreview}
                  </div>
                )}
                {taskResult && taskResult.summary && (
                  <div className="px-3 pb-1 text-xs text-[var(--text-secondary)] line-clamp-2">
                    {taskResult.summary}
                  </div>
                )}
                {taskResult && (
                  <div className="px-3 pb-1">
                    <button
                      onClick={(e) => {
                        e.stopPropagation()
                        onNavigateToSubAgent?.(taskResult.task_id, taskDescription || '子智能体任务', subagentType)
                      }}
                      className="text-xs text-[var(--accent-cyan)] hover:text-[var(--accent-cyan)]/80 hover:underline transition-colors flex items-center gap-1"
                    >
                      <span>查看完整会话</span>
                      <span>→</span>
                    </button>
                  </div>
                )}
                {isTaskTool && message.navigateToTaskId && !taskResult && (
                  <div className="px-3 pb-1">
                    <button
                      onClick={(e) => {
                        e.stopPropagation()
                        onNavigateToSubAgent?.(message.navigateToTaskId!, taskDescription || '子智能体任务', subagentType)
                      }}
                      className="text-xs text-[var(--accent-cyan)] hover:text-[var(--accent-cyan)]/80 hover:underline transition-colors flex items-center gap-1"
                    >
                      <span>查看实时进度</span>
                      <span>→</span>
                    </button>
                  </div>
                )}
                {isTaskTool && !taskResult && !message.navigateToTaskId && (
                  <div className="px-3 pb-2 text-xs text-[var(--text-muted)]">
                    子智能体正在执行...
                  </div>
                )}
              </>
            )}

            {/* Expanded */}
            {toolExpanded && (
              <div className="border-t border-[var(--border-color)] px-3 py-2 space-y-2">
                {/* 模型思考内容（展开时也展示） */}
                {showThinking && message.reasoningContent && (
                  <div className="mb-2">
                    <ThinkingSection content={message.reasoningContent} />
                  </div>
                )}
                {taskResult ? (
                  <>
                    {taskPrompt && (
                      <div>
                        <div className="text-xs font-medium text-[var(--text-muted)] mb-1">任务指令</div>
                        <pre className="text-xs text-[var(--text-secondary)] font-mono whitespace-pre-wrap bg-[var(--overlay-dim)] rounded-lg p-2 overflow-x-auto max-h-32 overflow-y-auto">
                          {taskPrompt}
                        </pre>
                      </div>
                    )}
                    {taskResult.summary && (
                      <div className={`rounded-lg px-3 py-2 ${
                        taskResult.status === 'success' ? 'bg-emerald-500/10 border border-emerald-500/30' :
                        taskResult.status === 'failed' ? 'bg-red-500/10 border border-red-500/30' :
                        'bg-amber-500/10 border border-amber-500/30'
                      }`}>
                        <div className="text-xs font-medium text-[var(--text-muted)] mb-0.5">摘要</div>
                        <div className="text-sm text-[var(--text-secondary)]">{taskResult.summary}</div>
                      </div>
                    )}
                    <div>
                      <div className="text-xs font-medium text-[var(--text-muted)] mb-1">输出</div>
                      <div className="markdown-content text-sm leading-relaxed bg-[var(--overlay-dim)] rounded-lg p-3 max-h-96 overflow-y-auto">
                        <ReactMarkdown remarkPlugins={[remarkGfm]}>
                          {taskResult.output}
                        </ReactMarkdown>
                      </div>
                    </div>
                    <div className="text-xs text-[var(--text-muted)] font-mono select-all">
                      task_id: {taskResult.task_id}
                    </div>
                    <button
                      onClick={(e) => {
                        e.stopPropagation()
                        onNavigateToSubAgent?.(taskResult.task_id, taskDescription || '子智能体任务', subagentType)
                      }}
                      className="text-xs text-[var(--accent-cyan)] hover:text-[var(--accent-cyan)]/80 hover:underline transition-colors flex items-center gap-1"
                    >
                      <span>查看完整会话</span>
                      <span>→</span>
                    </button>
                  </>
                ) : (
                  <>
                    {hasArgs && (
                      <div>
                        <div className="text-xs font-medium text-[var(--text-muted)] mb-1">参数</div>
                        <pre className="text-xs text-[var(--text-secondary)] font-mono whitespace-pre-wrap bg-[var(--overlay-dim)] rounded-lg p-2 overflow-x-auto">
                          {JSON.stringify(message.arguments, null, 2)}
                        </pre>
                      </div>
                    )}
                    {hasResult && (
                      <div>
                        <div className="text-xs font-medium text-[var(--text-muted)] mb-1">结果</div>
                        <pre className="text-xs text-[var(--text-secondary)] font-mono whitespace-pre-wrap bg-[var(--overlay-dim)] rounded-lg p-2 overflow-x-auto max-h-48 overflow-y-auto">
                          {formatJSON(displayContent)}
                        </pre>
                      </div>
                    )}
                    {isTaskTool && message.navigateToTaskId && (
                      <button
                        onClick={(e) => {
                          e.stopPropagation()
                          onNavigateToSubAgent?.(message.navigateToTaskId!, taskDescription || '子智能体任务', subagentType)
                        }}
                        className="text-xs text-[var(--accent-cyan)] hover:text-[var(--accent-cyan)]/80 hover:underline transition-colors flex items-center gap-1"
                      >
                        <span>查看实时进度</span>
                        <span>→</span>
                      </button>
                    )}
                  </>
                )}
              </div>
            )}
          </div>
        </div>
        {lightboxElement}
        {showDetailModal && (
          <ToolDetailModal
            toolName={message.toolName || 'Tool'}
            status={status}
            statusLabel={status === 'calling' ? '执行中' : status === 'result' ? '已完成' : status === 'pending' ? '待确认' : status}
            arguments={message.arguments}
            resultContent={message.resultContent || ''}
            callContent={message.callContent || ''}
            durationMs={message.durationMs}
            onClose={() => setShowDetailModal(false)}
          />
        )}
      </div>
    )
  }

  // 隐藏思考且无实质内容时，不渲染空的助手消息气泡
  if (!isUser && !isTool && !isMergedTool && !showThinking && !message.content.trim() && message.reasoningContent) {
    return null
  }

  const getIcon = () => {
    if (isUser) return <User className="h-4 w-4" />
    if (isTool) {
      if (message.type === 'tool_call') return <Terminal className="h-4 w-4" />
      if (message.type === 'tool_result') return <CheckCircle className="h-4 w-4" />
      if (message.type === 'tool_pending') return <AlertCircle className="h-4 w-4" />
      return <Wrench className="h-4 w-4" />
    }
    return <Bot className="h-4 w-4" />
  }

  const getContainerStyles = () => {
    if (isUser) {
      return 'bg-gradient-to-br from-[var(--accent-cyan)]/20 to-[var(--accent-blue)]/20 border-[var(--accent-cyan)]/30 text-[var(--text-primary)]'
    }
    if (isTool) {
      if (message.type === 'tool_call') return 'bg-amber-500/10 border-amber-500/30 text-amber-100'
      if (message.type === 'tool_result') return 'bg-emerald-500/10 border-emerald-500/30 text-emerald-100'
      if (message.type === 'tool_pending') return 'bg-orange-500/10 border-orange-500/30 text-orange-100'
      return 'bg-[var(--bg-hover)] border-[var(--border-color)] text-[var(--text-secondary)]'
    }
    return 'bg-[var(--bg-tertiary)] border-[var(--border-color)] text-[var(--text-primary)]'
  }

  const getAvatarStyles = () => {
    if (isUser) return 'bg-gradient-to-br from-[var(--accent-cyan)] to-[var(--accent-blue)]'
    if (isTool) {
      if (message.type === 'tool_call') return 'bg-amber-500'
      if (message.type === 'tool_result') return 'bg-emerald-500'
      if (message.type === 'tool_pending') return 'bg-orange-500'
      return 'bg-zinc-700'
    }
    return 'bg-gradient-to-br from-[var(--accent-purple)] to-[#ec4899]'
  }

  return (
    <div data-message-id={message.id} className={`flex gap-4 ${isUser ? 'flex-row-reverse' : 'flex-row'} animate-slide-in group`}>
      <div
        className={`flex h-8 w-8 shrink-0 items-center justify-center rounded-full ${getAvatarStyles()} shadow-lg`}
      >
        {getIcon()}
      </div>
      <div className={`max-w-[80%] ${isUser ? 'text-right' : 'text-left'}`}>
        <div className="flex items-center gap-2 mb-1">
          <span className={`text-xs font-medium ${isUser ? 'text-[var(--accent-cyan)]' : 'text-[var(--text-secondary)]'}`}>
            {isUser ? 'You' : isTool ? message.toolName || 'Tool' : 'Assistant'}
          </span>
          <span className="text-xs text-[var(--text-muted)]">{formatTime(message.timestamp)}</span>
          <CopyButton text={message.content} />
        </div>
        <div
          className={`inline-block rounded-2xl border px-5 py-3 text-left shadow-lg ${getContainerStyles()}`}
        >
          {isTool && message.toolName && (
            <div className="mb-2 text-xs font-semibold opacity-70 flex items-center gap-1">
              <Terminal className="h-3 w-3" />
              {message.toolName}
            </div>
          )}
          {isUser ? (
            // 用户消息保持纯文本
            <div className="whitespace-pre-wrap text-sm leading-relaxed">{message.content}</div>
          ) : (
            // 模型思考内容（仅助手消息，非工具消息）
            <>
            {showThinking && !isTool && message.reasoningContent && (
              <div className={message.content.trim() ? 'mb-3' : ''}>
                <ThinkingSection content={message.reasoningContent} />
              </div>
            )}
            {/* AI 和工具消息使用 Markdown 渲染 */}
            {message.content.trim() && (
            <div className="markdown-content text-sm leading-relaxed">
              <ReactMarkdown
                remarkPlugins={[remarkGfm]}
                components={{
                  // 自定义代码块渲染
                  code({ className, children, ...props }) {
                    const isInline = !className
                    if (isInline) {
                      return (
                        <code
                          className="bg-[var(--overlay-code)] px-1.5 py-0.5 rounded text-[var(--accent-cyan)] font-mono text-xs"
                          {...props}
                        >
                          {children}
                        </code>
                      )
                    }
                    return (
                      <pre className="bg-[var(--overlay-dim-heavy)] rounded-lg p-3 overflow-x-auto my-2">
                        <code className={`${className} font-mono text-xs`} {...props}>
                          {children}
                        </code>
                      </pre>
                    )
                  },
                  // 标题样式
                  h1: ({ children }) => (
                    <h1 className="text-xl font-bold text-[var(--text-primary)] mb-2 mt-4">{children}</h1>
                  ),
                  h2: ({ children }) => (
                    <h2 className="text-lg font-bold text-[var(--text-primary)] mb-2 mt-3">{children}</h2>
                  ),
                  h3: ({ children }) => (
                    <h3 className="text-base font-bold text-[var(--text-primary)] mb-1 mt-2">{children}</h3>
                  ),
                  // 段落
                  p: ({ children }) => <p className="mb-2 last:mb-0">{children}</p>,
                  // 列表
                  ul: ({ children }) => <ul className="list-disc list-outside mb-2 space-y-1 pl-5">{children}</ul>,
                  ol: ({ children }) => <ol className="list-decimal list-outside mb-2 space-y-1 pl-5">{children}</ol>,
                  li: ({ children }) => <li className="[&>p]:m-0">{children}</li>,
                  // 链接
                  a: ({ href, children }) => (
                    <a
                      href={href}
                      target="_blank"
                      rel="noopener noreferrer"
                      className="text-[var(--accent-cyan)] hover:underline"
                    >
                      {children}
                    </a>
                  ),
                  // 表格
                  table: ({ children }) => (
                    <table className="w-full border-collapse mb-2 text-xs">{children}</table>
                  ),
                  thead: ({ children }) => <thead className="bg-[var(--overlay-subtle)]">{children}</thead>,
                  th: ({ children }) => (
                    <th className="border border-[var(--border-color)] px-2 py-1 text-left font-semibold">{children}</th>
                  ),
                  td: ({ children }) => (
                    <td className="border border-[var(--border-color)] px-2 py-1">{children}</td>
                  ),
                  // 引用块
                  blockquote: ({ children }) => (
                    <blockquote className="border-l-2 border-[var(--accent-cyan)]/50 pl-3 my-2 text-[var(--text-secondary)]">
                      {children}
                    </blockquote>
                  ),
                  // 分隔线
                  hr: () => <hr className="border-[var(--border-color)] my-3" />,
                  // 加粗和斜体
                  strong: ({ children }) => <strong className="font-bold text-[var(--text-primary)]">{children}</strong>,
                  em: ({ children }) => <em className="italic text-[var(--text-secondary)]">{children}</em>,
                }}
              >
                {message.content}
              </ReactMarkdown>
            </div>
            )}
          </>)}
          {message.attachments && message.attachments.length > 0 && (
            <div className="mt-2 space-y-2">
              {message.attachments.some(att => att.media_type === 'image' && att.content_base64) && (
                <div className="flex flex-wrap gap-2">
                  {message.attachments
                    .filter(att => att.media_type === 'image' && att.content_base64)
                    .map((att, idx) => (
                      <img
                        key={`img-${idx}`}
                        src={`data:${att.mime_type || 'image/png'};base64,${att.content_base64}`}
                        alt={att.file_name || att.path || '图片'}
                        className="max-w-64 max-h-48 rounded-xl object-cover cursor-pointer border border-[var(--border-color)] hover:border-[var(--accent-cyan)]/40 hover:scale-[1.02] transition-all duration-200 shadow-md"
                        onClick={() => setLightboxImage({ base64: att.content_base64!, mimeType: att.mime_type || 'image/png', fileName: att.file_name || att.path })}
                      />
                    ))}
                </div>
              )}
              {message.attachments
                .filter(att => att.media_type !== 'image' || !att.content_base64)
                .map((att, idx) => (
                  <AttachmentCard key={`att-${idx}`} attachment={att} />
                ))}
            </div>
          )}
        </div>
      </div>
      {lightboxElement}
    </div>
  )
}
