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

// 模块级常量：保持引用稳定，避免流式渲染期间每帧重建
// （react-markdown 收到新的 components/plugins 引用会重走内部映射与解析）。
const REMARK_PLUGINS = [remarkGfm];

const MARKDOWN_COMPONENTS: 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>,
};

// 状态图标组件
function StatusIcon({
  status,
  size = 14,
}: {
  status: string;
  size?: number;
}) {
  const iconClass = `transition-all duration-300`;

  switch (status) {
    case 'calling':
    case 'running':
      return (
        <Loader2
          className={`${iconClass} animate-spin`}
          style={{ width: size, height: size }}
          strokeWidth={2.5}
        />
      );
    case 'result':
    case 'success':
    case 'completed':
      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':
    case 'interrupted':
    case 'cancelled':
      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;
  /** 主代理当前生效模型（Task 卡片差异显示：子代理模型不同才展示模型徽章） */
  effectiveModel?: { provider: string; model: string } | null;
}

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`;
}

/**
 * base64 → Blob 分块解码。
 * 旧实现为 atob 全量字符串 + 装箱数字数组 + 单个巨型 Uint8Array，
 * 50MB 附件下载瞬时占用数百 MB；分块构造后 Blob 直接接收分片，
 * 峰值内存约为 atob 字符串 + 单个分块大小。
 */
function base64ToBlob(base64: string, mimeType: string): Blob {
  const byteChars = atob(base64);
  const total = byteChars.length;
  const CHUNK_SIZE = 0x8000; // 32K
  const parts: Uint8Array<ArrayBuffer>[] = [];
  for (let offset = 0; offset < total; offset += CHUNK_SIZE) {
    const slice = byteChars.slice(offset, offset + CHUNK_SIZE);
    parts.push(Uint8Array.from(slice, (c) => c.charCodeAt(0)));
  }
  return new Blob(parts, { type: mimeType });
}

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 blob = base64ToBlob(attachment.content_base64, 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 blob = base64ToBlob(src, 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-[var(--accent-green)]" />
      ) : (
        <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 const MessageBubble = memo(function MessageBubble({
  message,
  onNavigateToSubAgent,
  showThinking = true,
  effectiveModel,
}: 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-[var(--accent-cyan)] animate-pulse',
        fullBorder: 'border-[var(--accent-cyan)]/30',
        iconColor: 'text-[var(--accent-cyan)]',
        avatarBg: 'bg-[var(--accent-cyan)]/10',
        avatarIcon: 'text-[var(--accent-cyan)]',
      },
      result: {
        dot: 'bg-[var(--accent-green)]',
        fullBorder: 'border-[var(--accent-green)]/30',
        iconColor: 'text-[var(--accent-green)]',
        avatarBg: 'bg-[var(--accent-green)]/10',
        avatarIcon: 'text-[var(--accent-green)]',
      },
      pending: {
        dot: 'bg-[var(--accent-amber)] animate-pulse',
        fullBorder: 'border-[var(--accent-amber)]/30',
        iconColor: 'text-[var(--accent-amber)]',
        avatarBg: 'bg-[var(--accent-amber)]/10',
        avatarIcon: 'text-[var(--accent-amber)]',
      },
    }[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 专用的状态配色
    // 支持的状态：
    // - running: 异步子代理刚 spawn，占位结果
    // - success/completed: 子代理执行成功
    // - failed: 子代理执行失败
    // - timeout: 子代理执行超时
    // - cancelled: 子代理被用户取消
    // - interrupted: 子代理因服务器重启被中断
    const taskStatusConfig: Record<string, { dot: string; borderColor: string; iconColor: string }> = {
      running: {
        dot: 'bg-[var(--accent-amber)] animate-pulse',
        borderColor: 'border-[var(--accent-amber)]/40',
        iconColor: 'text-[var(--accent-amber)]',
      },
      success: {
        dot: 'bg-[var(--accent-green)]',
        borderColor: 'border-[var(--accent-green)]/40',
        iconColor: 'text-[var(--accent-green)]',
      },
      completed: {
        dot: 'bg-[var(--accent-green)]',
        borderColor: 'border-[var(--accent-green)]/40',
        iconColor: 'text-[var(--accent-green)]',
      },
      failed: {
        dot: 'bg-[rgb(242,90,90)]',
        borderColor: 'border-[rgb(242,90,90)]/40',
        iconColor: 'text-[rgb(242,90,90)]',
      },
      timeout: {
        dot: 'bg-[var(--accent-amber)]',
        borderColor: 'border-[var(--accent-amber)]/40',
        iconColor: 'text-[var(--accent-amber)]',
      },
      cancelled: {
        dot: 'bg-[var(--text-muted)]',
        borderColor: 'border-[var(--border-color)]',
        iconColor: 'text-[var(--text-muted)]',
      },
      interrupted: {
        dot: 'bg-[var(--accent-amber)]',
        borderColor: 'border-[var(--accent-amber)]/40',
        iconColor: 'text-[var(--accent-amber)]',
      },
    };

    // 安全获取 task 状态配色，未知状态回退到默认（避免 undefined.borderColor 崩溃）
    const taskStyle = taskResult ? (taskStatusConfig[taskResult.status] ?? taskStatusConfig.failed) : null;

    // 子代理模型徽章：结果携带模型信息，且（无主代理参照 或 model/provider 任一不同）时展示。
    // provider 不同即使 model 同名也显示——不同 provider 的同名模型在路由/计费上已不同。
    const modelDiffers =
      !effectiveModel ||
      effectiveModel.model !== taskResult?.model ||
      effectiveModel.provider !== taskResult?.provider;
    const subagentModelLabel =
      taskResult?.model && modelDiffers
        ? effectiveModel && effectiveModel.provider === taskResult.provider
          ? taskResult.model
          : `${taskResult.provider ?? '?'}/${taskResult.model}`
        : null;

    return (
      <div data-message-id={message.id} className="animate-slide-in">
        <div
          onClick={() => setToolExpanded(!toolExpanded)}
          className={`group w-full cursor-pointer rounded-xl border bg-[var(--bg-secondary)]/60 transition-colors duration-300 hover:bg-[var(--bg-secondary)] ${
            taskStyle ? taskStyle.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 ${
                  taskStyle ? taskStyle.dot : statusConfig.dot
                }`}
              />
              <span className="text-sm font-medium text-[var(--text-secondary)] truncate">
                {isTaskTool
                  ? `${message.toolName || 'Tool'}${taskDescription ? ` · ${taskDescription}` : ''}`
                  : message.toolName || 'Tool'}
              </span>
              {subagentModelLabel && (
                <span
                  className="flex-shrink-0 rounded-full border border-[var(--border-color)] bg-[var(--bg-tertiary)] px-1.5 py-px text-[10px] leading-4 text-[var(--text-muted)] max-w-[160px] truncate"
                  title={`子代理模型：${taskResult?.provider ?? '?'} / ${taskResult?.model}`}
                >
                  {subagentModelLabel}
                </span>
              )}
              <span
                className={`flex-shrink-0 transition-all duration-300 ${
                  taskStyle ? taskStyle.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-[var(--accent-green)]/10 border border-[var(--accent-green)]/30'
                            : taskResult.status === 'failed'
                              ? 'bg-[rgb(242,90,90)]/10 border border-[rgb(242,90,90)]/30'
                              : 'bg-[var(--accent-amber)]/10 border border-[var(--accent-amber)]/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={REMARK_PLUGINS}>
                          {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>
        {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>
    );
  }

  // 隐藏无可见内容的助手消息（无文本，且无思考或思考被关闭）
  const hasVisibleContent =
    !!(message.content && message.content.trim()) || (showThinking && message.reasoningContent);
  if (!isUser && !isTool && !isMergedTool && !hasVisibleContent) {
    return null;
  }



  return (
    <div
      data-message-id={message.id}
      className={`animate-slide-in group ${isUser ? 'flex flex-col items-end' : ''}`}
    >
      {!isUser && (
        <div className="mb-1 flex items-center gap-2">
          {isTool && message.toolName ? (
            <span className="text-xs font-medium text-[var(--text-secondary)]">
              {message.toolName}
            </span>
          ) : null}
          <span className="text-xs text-[var(--text-muted)] opacity-0 transition-opacity group-hover:opacity-100">
            {formatTime(message.timestamp)}
          </span>
          <CopyButton text={message.content} />
        </div>
      )}
      <div
        className={
          isUser
            ? 'max-w-[min(525px,82%)] rounded-[22px] bg-[var(--bubble-user)] px-4 py-2.5 text-left'
            : 'w-full min-w-0'
        }
      >
        {isUser ? (
          // 用户消息保持纯文本（右对齐柔和气泡）
          <div className="whitespace-pre-wrap text-[15px] leading-6 text-[var(--text-primary)]">
            {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-[15px] leading-6">
                  <ReactMarkdown
                    remarkPlugins={REMARK_PLUGINS}
                    components={MARKDOWN_COMPONENTS}
                  >
                    {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>
      {isUser && (
        <div className="mt-1 flex items-center gap-2 px-1">
          <span className="text-xs text-[var(--text-muted)] opacity-0 transition-opacity group-hover:opacity-100">
            {formatTime(message.timestamp)}
          </span>
          <CopyButton text={message.content} />
        </div>
      )}
      {lightboxElement}
    </div>
  );
});
