import { useEffect, useRef, useState, useMemo, memo, useCallback, lazy, Suspense, useLayoutEffect } from 'react';
import { useVirtualizer } from '@tanstack/react-virtual';
import TextareaAutosize from 'react-textarea-autosize';
import {
  User, Bot, Terminal, CheckCircle, AlertCircle, Info,
  FileText, Search, FolderSearch, Pencil, FilePlus, Globe,
  ChevronDown, ChevronRight, Play, ArrowDown,
  ClipboardList, Brain, Paperclip, Image, HelpCircle, Zap, Command
} from 'lucide-react';
import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import { useAuth } from '../contexts/AuthContext';
import { useHosts } from '../contexts/HostContext';

// Lazy load SyntaxHighlighter - saves ~500KB from initial bundle
const SyntaxHighlighter = lazy(() =>
  import('react-syntax-highlighter').then(mod => ({
    default: mod.Prism
  }))
);

// Import style separately (small JSON, OK to load eagerly for consistency)
import { oneDark } from 'react-syntax-highlighter/dist/esm/styles/prism';

// Fallback component for code blocks while SyntaxHighlighter loads
const CodeFallback = memo(function CodeFallback({ children }) {
  return (
    <pre className="bg-dark-900 rounded-lg p-3 text-xs text-dark-300 font-mono overflow-x-auto animate-pulse">
      <code>{children}</code>
    </pre>
  );
});

// Wrapper for lazy-loaded SyntaxHighlighter with Suspense
const LazyCodeBlock = memo(function LazyCodeBlock({ language, style, customStyle, children, ...props }) {
  return (
    <Suspense fallback={<CodeFallback>{children}</CodeFallback>}>
      <SyntaxHighlighter
        language={language}
        style={style}
        customStyle={customStyle}
        {...props}
      >
        {children}
      </SyntaxHighlighter>
    </Suspense>
  );
});

// Helper to extract and filter system-reminder tags
function parseSystemReminders(text) {
  if (!text || typeof text !== 'string') return { content: text || '', reminders: [] };

  const reminders = [];
  const reminderRegex = /<system-reminder>([\s\S]*?)<\/system-reminder>/g;
  let match;
  while ((match = reminderRegex.exec(text)) !== null) {
    reminders.push(match[1].trim());
  }

  const content = text.replace(/<system-reminder>[\s\S]*?<\/system-reminder>/g, '').trim();
  return { content, reminders };
}

// Helper to extract thinking tags from content
function parseThinking(text) {
  if (!text || typeof text !== 'string') return { content: text || '', thinking: [] };

  const thinking = [];
  const thinkingRegex = /<thinking>([\s\S]*?)<\/thinking>/g;
  let match;
  while ((match = thinkingRegex.exec(text)) !== null) {
    thinking.push(match[1].trim());
  }

  const content = text.replace(/<thinking>[\s\S]*?<\/thinking>/g, '').trim();
  return { content, thinking };
}

// Collapsible thinking block component
function ThinkingBlock({ thinking }) {
  const [show, setShow] = useState(false);

  if (!thinking || thinking.length === 0) return null;

  return (
    <div className="mb-3">
      <button
        onClick={() => setShow(!show)}
        className="flex items-center gap-2 text-xs text-purple-400 hover:text-purple-300 transition-colors"
      >
        <Brain className="w-3.5 h-3.5" />
        <span>Thinking</span>
        {show ? <ChevronDown className="w-3 h-3" /> : <ChevronRight className="w-3 h-3" />}
      </button>
      {show && (
        <div className="mt-2 p-3 bg-purple-900/10 border border-purple-500/20 rounded-lg">
          {thinking.map((thought, idx) => (
            <div key={idx} className="text-sm text-purple-300/80 italic whitespace-pre-wrap">
              {thought}
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

// Collapsible system hints component
function SystemHints({ reminders, inline = false }) {
  const [show, setShow] = useState(false);

  if (!reminders || reminders.length === 0) return null;

  if (inline) {
    return (
      <span className="inline-flex items-center gap-1 ml-2">
        <button
          onClick={() => setShow(!show)}
          className="inline-flex items-center gap-1 text-xs text-purple-400 hover:text-purple-300 transition-colors"
        >
          <Info className="w-3 h-3" />
          <span>{reminders.length} hint{reminders.length > 1 ? 's' : ''}</span>
          {show ? <ChevronDown className="w-3 h-3" /> : <ChevronRight className="w-3 h-3" />}
        </button>
      </span>
    );
  }

  return (
    <>
      <button
        onClick={() => setShow(!show)}
        className="flex items-center gap-1 text-xs text-purple-400 hover:text-purple-300 transition-colors mt-2"
      >
        <Info className="w-3 h-3" />
        <span>{reminders.length} system hint{reminders.length > 1 ? 's' : ''}</span>
        {show ? <ChevronDown className="w-3 h-3" /> : <ChevronRight className="w-3 h-3" />}
      </button>
      {show && (
        <div className="mt-2 border-t border-purple-500/20 bg-purple-900/10 rounded-lg p-2.5">
          {reminders.map((reminder, idx) => (
            <div key={idx} className="text-xs text-purple-300/70 font-mono whitespace-pre-wrap mb-2 last:mb-0">
              <span className="text-purple-400 font-semibold">System Hint {idx + 1}:</span>
              <div className="mt-1 pl-2 border-l-2 border-purple-500/30 max-h-32 overflow-y-auto">
                {reminder}
              </div>
            </div>
          ))}
        </div>
      )}
    </>
  );
}

// Custom comparison for MessageList - only re-render when these specific things change
const messageListPropsAreEqual = (prev, next) => {
  // Check if messages array length changed
  if (prev.messages.length !== next.messages.length) return false;

  // Check if last message content changed (for streaming)
  if (prev.messages.length > 0 && next.messages.length > 0) {
    const prevLast = prev.messages[prev.messages.length - 1];
    const nextLast = next.messages[next.messages.length - 1];
    if (prevLast.content !== nextLast.content) return false;
    if (prevLast.type !== nextLast.type) return false;
  }

  // Check other props
  return (
    prev.isProcessing === next.isProcessing &&
    prev.onSendMessage === next.onSendMessage &&
    prev.hostId === next.hostId
  );
};

export const MessageList = memo(function MessageList({ messages, isProcessing, onSendMessage, hostId }) {
  const { hosts } = useHosts();
  const hostConfig = hosts[hostId] || null;
  const containerRef = useRef(null);
  const [showScrollButton, setShowScrollButton] = useState(false);
  const [newMessageCount, setNewMessageCount] = useState(0);
  const prevMessageCount = useRef(messages.length);
  const userScrolledAway = useRef(false);
  const prevHostId = useRef(hostId);

  // Cache for incremental updates - avoid full rebuild on streaming content changes
  // Moved up so it's available for the reset effect
  const processedCacheRef = useRef({ messages: [], result: [], toolResultMap: new Map() });

  // Reset scroll state when switching sessions (hostId changes or messages array replaced)
  // This fixes the "scroll to bottom" button appearing incorrectly after switching from split view
  useLayoutEffect(() => {
    // Detect session change by checking if hostId changed or if messages were reset
    const hostChanged = prevHostId.current !== hostId;
    const messagesReset = messages.length === 0 ||
      (prevMessageCount.current > 0 && messages.length > 0 &&
       messages[0]?.timestamp !== processedCacheRef.current.messages[0]?.timestamp);

    if (hostChanged || messagesReset) {
      // Reset all scroll-related state
      userScrolledAway.current = false;
      setShowScrollButton(false);
      setNewMessageCount(0);
      prevMessageCount.current = messages.length;
      prevHostId.current = hostId;

      // Clear processed cache to force rebuild
      processedCacheRef.current = { messages: [], result: [], toolResultMap: new Map() };

      // Scroll to bottom after session switch
      if (containerRef.current) {
        requestAnimationFrame(() => {
          if (containerRef.current) {
            containerRef.current.scrollTop = containerRef.current.scrollHeight;
          }
        });
      }
    }
  }, [hostId, messages]);

  // Check if scrolled to bottom
  const checkIfAtBottom = useCallback(() => {
    if (!containerRef.current) return true;
    const { scrollTop, scrollHeight, clientHeight } = containerRef.current;
    return scrollHeight - scrollTop - clientHeight < 150;
  }, []);

  // Handle scroll
  const handleScroll = useCallback(() => {
    const atBottom = checkIfAtBottom();
    if (atBottom) {
      userScrolledAway.current = false;
      setShowScrollButton(false);
      setNewMessageCount(0);
    } else {
      userScrolledAway.current = true;
      setShowScrollButton(true);
    }
  }, [checkIfAtBottom]);

  // Preprocess messages to pair tool_use with tool_result
  // Optimized: only rebuild when structure changes, not content
  const processedMessages = useMemo(() => {
    const cache = processedCacheRef.current;

    // Fast path: if only last message content changed (streaming), return cached result
    if (cache.messages.length === messages.length && messages.length > 0) {
      const lastCached = cache.messages[cache.messages.length - 1];
      const lastCurrent = messages[messages.length - 1];

      // Check if structure is same (only content might have changed)
      if (lastCached.type === lastCurrent.type &&
          lastCached.timestamp === lastCurrent.timestamp &&
          lastCached.toolUseId === lastCurrent.toolUseId) {
        // Content update only - update the cached result's last item content
        if (cache.result.length > 0 && lastCurrent.type === 'assistant') {
          cache.result[cache.result.length - 1] = {
            ...cache.result[cache.result.length - 1],
            content: lastCurrent.content
          };
        }
        return cache.result;
      }
    }

    // Full rebuild needed
    const result = [];
    const toolResultMap = new Map();

    // First pass: collect all tool_results by toolUseId
    messages.forEach(msg => {
      if (msg.type === 'tool_result' && msg.toolUseId) {
        toolResultMap.set(msg.toolUseId, msg);
      }
    });

    // Second pass: build processed list, attaching results to tool_use
    messages.forEach((msg, index) => {
      if (msg.type === 'tool_use') {
        const toolResult = toolResultMap.get(msg.toolUseId);
        result.push({
          ...msg,
          _pairedResult: toolResult || null,
          _originalIndex: index,
        });
      } else if (msg.type === 'tool_result') {
        // Skip tool_results that were paired with a tool_use
        if (!toolResultMap.has(msg.toolUseId) || !messages.some(m => m.type === 'tool_use' && m.toolUseId === msg.toolUseId)) {
          // Orphan tool_result (no matching tool_use), show it standalone
          result.push({ ...msg, _originalIndex: index });
        }
        // Otherwise skip - it's already paired
      } else {
        result.push({ ...msg, _originalIndex: index });
      }
    });

    // Update cache
    cache.messages = messages;
    cache.result = result;
    cache.toolResultMap = toolResultMap;

    return result;
  }, [messages]);

  // Virtualizer for efficient rendering of large message lists
  // Estimate height based on message type
  const estimateSize = useCallback((index) => {
    const msg = processedMessages[index];
    if (!msg) return 100;
    switch (msg.type) {
      case 'user': return 80;
      case 'assistant': return 200;
      case 'tool_use': return 150;
      case 'tool_result': return 120;
      case 'system': return 40;
      case 'error': return 80;
      default: return 100;
    }
  }, [processedMessages]);

  const virtualizer = useVirtualizer({
    count: processedMessages.length + (isProcessing ? 1 : 0), // +1 for processing indicator
    getScrollElement: () => containerRef.current,
    estimateSize,
    overscan: 5, // Render 5 extra items above/below viewport
    measureElement: (element) => {
      // Measure actual element height for dynamic sizing
      return element?.getBoundingClientRect().height ?? estimateSize(0);
    },
  });

  // Auto-scroll to bottom when new messages arrive or content changes (if not scrolled away)
  useLayoutEffect(() => {
    // Skip if user manually scrolled away
    if (userScrolledAway.current) {
      const newCount = messages.length - prevMessageCount.current;
      if (newCount > 0) {
        setNewMessageCount(prev => prev + newCount);
      }
      prevMessageCount.current = messages.length;
      return;
    }

    // Use native scroll for reliability - virtualizer.scrollToIndex can be unreliable
    if (containerRef.current && processedMessages.length > 0) {
      // Small delay to let DOM update after content change
      requestAnimationFrame(() => {
        if (containerRef.current && !userScrolledAway.current) {
          containerRef.current.scrollTop = containerRef.current.scrollHeight;
        }
      });
    }
    prevMessageCount.current = messages.length;
  }, [messages, processedMessages.length, isProcessing]);

  // Also scroll on streaming content updates (last message content change)
  const lastMessageContent = messages[messages.length - 1]?.content;
  useLayoutEffect(() => {
    if (!userScrolledAway.current && containerRef.current && lastMessageContent) {
      requestAnimationFrame(() => {
        if (containerRef.current && !userScrolledAway.current) {
          containerRef.current.scrollTop = containerRef.current.scrollHeight;
        }
      });
    }
  }, [lastMessageContent]);

  // Scroll to bottom function - use native scroll for reliability
  const scrollToBottomVirtual = useCallback(() => {
    userScrolledAway.current = false;
    if (containerRef.current) {
      containerRef.current.scrollTo({
        top: containerRef.current.scrollHeight,
        behavior: 'smooth'
      });
    }
    setShowScrollButton(false);
    setNewMessageCount(0);
  }, []);

  if (messages.length === 0) {
    return (
      <div className="flex-1 min-h-0 flex items-center justify-center p-8">
        <div className="text-center text-dark-500 max-w-md">
          <Bot className="w-16 h-16 mx-auto mb-4 opacity-50" />
          <h2 className="text-xl font-semibold mb-2">Welcome to Claude Web UI</h2>
          <p className="text-sm">
            Start a session and begin chatting with Claude.
            All messages are streamed in real-time via JSON.
          </p>
        </div>
      </div>
    );
  }

  const items = virtualizer.getVirtualItems();

  return (
    <div className="relative flex-1 min-h-0 overflow-hidden">
      <div
        ref={containerRef}
        onScroll={handleScroll}
        className="h-full overflow-y-auto"
      >
        {/* Virtual list container */}
        <div
          style={{
            height: `${virtualizer.getTotalSize()}px`,
            width: '100%',
            position: 'relative',
          }}
        >
          {items.map((virtualItem) => {
            const isProcessingIndicator = virtualItem.index === processedMessages.length;

            return (
              <div
                key={virtualItem.key}
                data-index={virtualItem.index}
                ref={virtualizer.measureElement}
                style={{
                  position: 'absolute',
                  top: 0,
                  left: 0,
                  width: '100%',
                  transform: `translateY(${virtualItem.start}px)`,
                }}
                className="px-4 py-2"
              >
                {isProcessingIndicator ? (
                  // Processing indicator
                  <div className="flex items-center gap-3 text-dark-400">
                    <Bot className="w-6 h-6" />
                    <div className="flex gap-1">
                      <span className="w-2 h-2 bg-orange-400 rounded-full typing-dot" />
                      <span className="w-2 h-2 bg-orange-400 rounded-full typing-dot" />
                      <span className="w-2 h-2 bg-orange-400 rounded-full typing-dot" />
                    </div>
                  </div>
                ) : (
                  <Message
                    message={processedMessages[virtualItem.index]}
                    onSendMessage={onSendMessage}
                    hostConfig={hostConfig}
                  />
                )}
              </div>
            );
          })}
        </div>
      </div>

      {/* Floating scroll-to-bottom button */}
      {showScrollButton && (
        <button
          onClick={scrollToBottomVirtual}
          className="absolute bottom-4 left-1/2 -translate-x-1/2 flex items-center gap-2 px-4 py-2 bg-orange-600 hover:bg-orange-500 text-white rounded-full shadow-lg transition-all duration-200 hover:scale-105 z-10"
        >
          <ArrowDown className="w-4 h-4" />
          <span className="text-sm font-medium">
            {newMessageCount > 0 ? `${newMessageCount} new` : 'Back to bottom'}
          </span>
        </button>
      )}
    </div>
  );
}, messageListPropsAreEqual);

// Memoize Message component to prevent re-renders during streaming
const Message = memo(function Message({ message, onSendMessage, hostConfig }) {
  const { type, content, tool, input, timestamp, toolUseId, attachments } = message;
  const { user } = useAuth();

  // Assistant name and avatar from host config
  const assistantName = hostConfig?.name || 'Claude';
  const assistantAvatar = hostConfig?.avatar || '🤖';

  // Memoize parsed system reminders and thinking for assistant messages
  const parsedContent = useMemo(() => {
    if (type === 'assistant') {
      const withoutReminders = parseSystemReminders(content);
      const withoutThinking = parseThinking(withoutReminders.content);
      return {
        content: withoutThinking.content,
        reminders: withoutReminders.reminders,
        thinking: withoutThinking.thinking,
      };
    }
    return null;
  }, [type, content]);

  const renderContent = () => {
    switch (type) {
      case 'user':
        const hasAttachments = attachments && attachments.length > 0;
        const imageCount = hasAttachments ? attachments.filter(a => a.isImage).length : 0;
        const fileCount = hasAttachments ? attachments.length - imageCount : 0;
        return (
          <div className="flex gap-3 message-enter">
            {user?.avatar ? (
              <img
                src={user.avatar}
                alt={user.name || 'You'}
                className="w-8 h-8 rounded-lg flex-shrink-0 object-cover"
              />
            ) : (
              <div className="w-8 h-8 rounded-lg bg-blue-600 flex items-center justify-center flex-shrink-0">
                <User className="w-4 h-4" />
              </div>
            )}
            <div className="max-w-[85%]">
              <div className="text-xs text-dark-500 mb-1">{user?.name?.split(' ')[0] || 'You'}</div>
              <div className="bg-dark-800 rounded-lg rounded-tl-none p-3 text-dark-100 inline-block">
                {/* Attachment badge */}
                {hasAttachments && (
                  <div className="flex items-center gap-2 mb-2 pb-2 border-b border-dark-700">
                    <Paperclip className="w-3.5 h-3.5 text-orange-400" />
                    <span className="text-xs text-orange-400">
                      {imageCount > 0 && (
                        <span className="inline-flex items-center gap-1 mr-2">
                          <Image className="w-3 h-3" />
                          {imageCount} image{imageCount > 1 ? 's' : ''}
                        </span>
                      )}
                      {fileCount > 0 && (
                        <span className="inline-flex items-center gap-1">
                          <FileText className="w-3 h-3" />
                          {fileCount} file{fileCount > 1 ? 's' : ''}
                        </span>
                      )}
                    </span>
                  </div>
                )}
                <pre className="whitespace-pre-wrap font-sans text-sm">{content}</pre>
              </div>
            </div>
          </div>
        );

      case 'assistant': {
        const { content: cleanContent, reminders, thinking } = parsedContent;
        return (
          <div className="flex gap-3 message-enter">
            {assistantAvatar?.startsWith('/') ? (
              <img
                src={assistantAvatar}
                alt={assistantName}
                className="w-8 h-8 rounded-lg object-cover flex-shrink-0"
              />
            ) : (
              <div className="w-8 h-8 rounded-lg bg-orange-600 flex items-center justify-center flex-shrink-0 text-lg">
                {assistantAvatar}
              </div>
            )}
            <div className="max-w-[85%]">
              <div className="text-xs text-dark-500 mb-1">{assistantName}</div>
              <div className="bg-dark-850 rounded-lg rounded-tl-none p-4 border border-dark-700 claude-message inline-block">
                <ThinkingBlock thinking={thinking} />
                <ReactMarkdown
                  remarkPlugins={[remarkGfm]}
                  components={{
                    code({ node, inline, className, children, ...props }) {
                      const match = /language-(\w+)/.exec(className || '');
                      return !inline && match ? (
                        <LazyCodeBlock
                          style={oneDark}
                          language={match[1]}
                          PreTag="div"
                          customStyle={{
                            margin: 0,
                            borderRadius: '0.5rem',
                            fontSize: '0.75rem',
                            fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace',
                          }}
                          {...props}
                        >
                          {String(children).replace(/\n$/, '')}
                        </LazyCodeBlock>
                      ) : (
                        <code className={className} {...props}>
                          {children}
                        </code>
                      );
                    }
                  }}
                >
                  {cleanContent}
                </ReactMarkdown>
                <SystemHints reminders={reminders} />
              </div>
            </div>
          </div>
        );
      }

      case 'tool_use':
        // Note: ExitPlanMode approval now handled via PermissionDialog modal
        // Just show it as a normal tool use card in the message list
        return <ToolUseCard tool={tool} input={input} result={message._pairedResult} onSendMessage={onSendMessage} />;

      case 'tool_result':
        return <ToolResultCard content={content} isSuccess={!message.isError} />;

      case 'system':
        return (
          <div className="flex items-center gap-2 justify-center message-enter">
            <Info className="w-4 h-4 text-dark-500" />
            <span className="text-xs text-dark-500">{content}</span>
          </div>
        );

      case 'error':
        return (
          <div className="flex gap-3 message-enter">
            <div className="w-8 h-8 rounded-lg bg-red-600/30 flex items-center justify-center flex-shrink-0">
              <AlertCircle className="w-4 h-4 text-red-400" />
            </div>
            <div className="flex-1 min-w-0">
              <div className="text-xs text-red-400 mb-1">Error</div>
              <div className="bg-red-900/20 rounded-lg p-3 text-red-300 border border-red-900/50 text-sm">
                {content}
              </div>
            </div>
          </div>
        );

      default:
        return (
          <div className="text-xs text-dark-500 ml-11">
            Unknown message type: {type}
          </div>
        );
    }
  };

  return <div>{renderContent()}</div>;
});

// Tool configuration with icons, colors, and display logic
const TOOL_CONFIG = {
  Read: {
    icon: FileText,
    color: 'blue',
    label: 'Reading file',
    getSummary: (input) => input.file_path?.split('/').slice(-2).join('/') || 'file',
  },
  Glob: {
    icon: FolderSearch,
    color: 'cyan',
    label: 'Searching files',
    getSummary: (input) => input.pattern || 'pattern',
  },
  Grep: {
    icon: Search,
    color: 'yellow',
    label: 'Searching content',
    getSummary: (input) => `"${input.pattern?.substring(0, 30)}${input.pattern?.length > 30 ? '...' : ''}"` || 'pattern',
  },
  Edit: {
    icon: Pencil,
    color: 'orange',
    label: 'Editing file',
    getSummary: (input) => input.file_path?.split('/').slice(-2).join('/') || 'file',
  },
  Write: {
    icon: FilePlus,
    color: 'green',
    label: 'Writing file',
    getSummary: (input) => input.file_path?.split('/').slice(-2).join('/') || 'file',
  },
  Bash: {
    icon: Terminal,
    color: 'purple',
    label: 'Running command',
    getSummary: (input) => {
      const desc = input.description;
      if (desc) return desc;
      const cmd = input.command || '';
      return cmd.length > 50 ? cmd.substring(0, 50) + '...' : cmd;
    },
  },
  WebFetch: {
    icon: Globe,
    color: 'pink',
    label: 'Fetching URL',
    getSummary: (input) => {
      try {
        const url = new URL(input.url || '');
        return url.hostname;
      } catch {
        return input.url?.substring(0, 30) || 'url';
      }
    },
  },
  WebSearch: {
    icon: Globe,
    color: 'cyan',
    label: 'Web search',
    getSummary: (input) => `"${input.query?.substring(0, 40)}${input.query?.length > 40 ? '...' : ''}"` || 'query',
  },
  Task: {
    icon: Play,
    color: 'indigo',
    label: 'Running agent',
    getSummary: (input) => input.description || input.subagent_type || 'task',
  },
  TodoWrite: {
    icon: CheckCircle,
    color: 'green',
    label: 'Updating todos',
    getSummary: (input) => {
      const todos = input.todos || [];
      const inProgress = todos.filter(t => t.status === 'in_progress').length;
      const completed = todos.filter(t => t.status === 'completed').length;
      return `${completed}/${todos.length} done${inProgress ? `, ${inProgress} active` : ''}`;
    },
  },
  NotebookEdit: {
    icon: FileText,
    color: 'orange',
    label: 'Editing notebook',
    getSummary: (input) => input.notebook_path?.split('/').pop() || 'notebook',
  },
  KillShell: {
    icon: Terminal,
    color: 'red',
    label: 'Killing shell',
    getSummary: (input) => input.shell_id || 'shell',
  },
  TaskOutput: {
    icon: Play,
    color: 'indigo',
    label: 'Getting task output',
    getSummary: (input) => input.task_id?.substring(0, 8) || 'task',
  },
  Skill: {
    icon: Zap,
    color: 'purple',
    label: 'Launching skill',
    getSummary: (input) => input.skill || 'skill',
  },
  SlashCommand: {
    icon: Command,
    color: 'cyan',
    label: 'Running command',
    getSummary: (input) => input.command?.split(' ')[0] || 'command',
  },
  AskUserQuestion: {
    icon: HelpCircle,
    color: 'yellow',
    label: 'Asking question',
    getSummary: (input) => {
      const questions = input.questions || [];
      if (questions.length === 1) return questions[0].header || 'question';
      return `${questions.length} questions`;
    },
    isInteractive: true,
  },
  ExitPlanMode: {
    icon: ClipboardList,
    color: 'purple',
    label: 'Plan Review',
    getSummary: () => 'Awaiting approval',
    isInteractive: true,
  },
  EnterPlanMode: {
    icon: Brain,
    color: 'purple',
    label: 'Entering Plan Mode',
    getSummary: () => 'Planning...',
  },
};

const COLOR_CLASSES = {
  blue: {
    bg: 'bg-blue-500/20',
    border: 'border-blue-500/30',
    text: 'text-blue-400',
    glow: 'shadow-blue-500/20',
  },
  cyan: {
    bg: 'bg-cyan-500/20',
    border: 'border-cyan-500/30',
    text: 'text-cyan-400',
    glow: 'shadow-cyan-500/20',
  },
  yellow: {
    bg: 'bg-yellow-500/20',
    border: 'border-yellow-500/30',
    text: 'text-yellow-400',
    glow: 'shadow-yellow-500/20',
  },
  orange: {
    bg: 'bg-orange-500/20',
    border: 'border-orange-500/30',
    text: 'text-orange-400',
    glow: 'shadow-orange-500/20',
  },
  green: {
    bg: 'bg-green-500/20',
    border: 'border-green-500/30',
    text: 'text-green-400',
    glow: 'shadow-green-500/20',
  },
  purple: {
    bg: 'bg-purple-500/20',
    border: 'border-purple-500/30',
    text: 'text-purple-400',
    glow: 'shadow-purple-500/20',
  },
  pink: {
    bg: 'bg-pink-500/20',
    border: 'border-pink-500/30',
    text: 'text-pink-400',
    glow: 'shadow-pink-500/20',
  },
  indigo: {
    bg: 'bg-indigo-500/20',
    border: 'border-indigo-500/30',
    text: 'text-indigo-400',
    glow: 'shadow-indigo-500/20',
  },
  red: {
    bg: 'bg-red-500/20',
    border: 'border-red-500/30',
    text: 'text-red-400',
    glow: 'shadow-red-500/20',
  },
};

// Note: PlanApprovalCard removed - ExitPlanMode approval now handled via PermissionDialog modal

// Separate component for custom input - uses uncontrolled input for lag-free typing
const CustomInputSection = memo(function CustomInputSection({ onSubmit, hasSelection }) {
  const textareaRef = useRef(null);
  const [hasText, setHasText] = useState(false);

  const canSubmit = hasSelection || hasText;

  const handleSubmit = useCallback(() => {
    const value = textareaRef.current?.value?.trim() || '';
    if (value) {
      onSubmit(value);
      if (textareaRef.current) {
        textareaRef.current.value = '';
        setHasText(false);
      }
    } else {
      onSubmit(null); // Signal to use selected options
    }
  }, [onSubmit]);

  // Only track whether there's text, not the actual content (for button state)
  const handleInput = useCallback(() => {
    const value = textareaRef.current?.value?.trim() || '';
    setHasText(value.length > 0);
  }, []);

  return (
    <div className="space-y-3 pt-3 border-t border-dark-700">
      {/* Custom input field - uncontrolled for performance */}
      <div className="space-y-2">
        <label className="text-xs text-dark-500 font-medium">Or type a custom response:</label>
        <TextareaAutosize
          ref={textareaRef}
          defaultValue=""
          onInput={handleInput}
          placeholder="Enter your own answer..."
          minRows={2}
          maxRows={6}
          cacheMeasurements
          className="w-full px-3 py-2 bg-dark-800 border border-dark-700 rounded-lg text-sm text-dark-200
            placeholder-dark-500 resize-none
            focus:outline-none focus:border-yellow-500/50 focus:ring-1 focus:ring-yellow-500/20
            transition-colors duration-200"
        />
      </div>

      {/* Submit button */}
      <button
        onClick={handleSubmit}
        disabled={!canSubmit}
        className={`w-full py-2.5 rounded-lg text-sm font-medium transition-all duration-200 ${
          canSubmit
            ? 'bg-yellow-500 text-dark-900 hover:bg-yellow-400 shadow-lg shadow-yellow-500/20 hover:shadow-yellow-500/30'
            : 'bg-dark-700 text-dark-500 cursor-not-allowed'
        }`}
      >
        Submit Answer
      </button>
    </div>
  );
});

const ToolUseCard = memo(function ToolUseCard({ tool, input, result, onSendMessage }) {
  const [showResult, setShowResult] = useState(false);
  const [selectedOptions, setSelectedOptions] = useState({});

  const config = TOOL_CONFIG[tool] || {
    icon: Terminal,
    color: 'purple',
    label: tool,
    getSummary: () => 'executing...',
  };

  const colors = COLOR_CLASSES[config.color] || COLOR_CLASSES.purple;
  const Icon = config.icon;
  const summary = config.getSummary(input);

  // Parse result content
  const resultData = useMemo(() => {
    if (!result) return null;

    let raw = '';
    const content = result.content;
    if (content === undefined || content === null) {
      raw = '(no content)';
    } else if (typeof content === 'string') {
      raw = content;
    } else if (Array.isArray(content)) {
      raw = content.map(c => {
        if (typeof c === 'string') return c;
        if (c?.type === 'text') return c.text || '';
        return JSON.stringify(c);
      }).join('\n');
    } else {
      raw = JSON.stringify(content, null, 2);
    }

    const parsed = parseSystemReminders(raw);
    const isSuccess = !result.isError;
    const chars = parsed.content.length;

    return {
      contentStr: parsed.content,
      systemReminders: parsed.reminders,
      isSuccess,
      chars,
    };
  }, [result]);

  // Format input for display
  const formatInput = () => {
    if (typeof input === 'string') return input;
    return JSON.stringify(input, null, 2);
  };

  // Render special input views for certain tools
  const renderSpecialInput = () => {
    if (tool === 'Edit' && input.old_string && input.new_string) {
      const oldLines = input.old_string.split('\n');
      const newLines = input.new_string.split('\n');
      const fileName = input.file_path?.split('/').pop() || 'file';

      return (
        <div className="space-y-2">
          {/* File header */}
          <div className="flex items-center gap-2 text-xs">
            <span className="text-dark-500">File:</span>
            <code className="text-orange-400">{input.file_path}</code>
          </div>

          {/* Diff view */}
          <div className="rounded overflow-hidden border border-dark-700 text-xs font-mono">
            {/* Removed lines */}
            <div className="bg-red-900/30">
              {oldLines.map((line, i) => (
                <div key={`old-${i}`} className="flex">
                  <span className="w-8 text-right pr-2 text-red-400/50 select-none border-r border-dark-700 bg-red-900/20">
                    {i + 1}
                  </span>
                  <span className="w-6 text-center text-red-400 select-none">-</span>
                  <span className="flex-1 text-red-300 pl-1 whitespace-pre-wrap break-all">{line || ' '}</span>
                </div>
              ))}
            </div>

            {/* Added lines */}
            <div className="bg-green-900/30 border-t border-dark-700">
              {newLines.map((line, i) => (
                <div key={`new-${i}`} className="flex">
                  <span className="w-8 text-right pr-2 text-green-400/50 select-none border-r border-dark-700 bg-green-900/20">
                    {i + 1}
                  </span>
                  <span className="w-6 text-center text-green-400 select-none">+</span>
                  <span className="flex-1 text-green-300 pl-1 whitespace-pre-wrap break-all">{line || ' '}</span>
                </div>
              ))}
            </div>
          </div>

          {/* Stats */}
          <div className="flex items-center gap-3 text-xs text-dark-500">
            <span className="text-red-400">-{oldLines.length} lines</span>
            <span className="text-green-400">+{newLines.length} lines</span>
          </div>
        </div>
      );
    }

    if (tool === 'Bash' && input.command) {
      return (
        <div className="space-y-2">
          <LazyCodeBlock
            language="bash"
            style={oneDark}
            customStyle={{ margin: 0, padding: '8px', fontSize: '11px', borderRadius: '4px' }}
          >
            {input.command}
          </LazyCodeBlock>
          {input.description && (
            <div className="text-xs text-dark-500">Description: {input.description}</div>
          )}
        </div>
      );
    }

    if (tool === 'Grep') {
      return (
        <div className="space-y-2">
          <div className="flex items-center gap-2">
            <span className="text-xs text-dark-500">Pattern:</span>
            <code className="text-xs text-yellow-400 bg-dark-800 px-2 py-0.5 rounded">{input.pattern}</code>
          </div>
          {input.path && (
            <div className="flex items-center gap-2">
              <span className="text-xs text-dark-500">Path:</span>
              <code className="text-xs text-dark-300">{input.path}</code>
            </div>
          )}
          {input.glob && (
            <div className="flex items-center gap-2">
              <span className="text-xs text-dark-500">Glob:</span>
              <code className="text-xs text-dark-300">{input.glob}</code>
            </div>
          )}
          {input.output_mode && (
            <div className="flex items-center gap-2">
              <span className="text-xs text-dark-500">Mode:</span>
              <code className="text-xs text-dark-300">{input.output_mode}</code>
            </div>
          )}
        </div>
      );
    }

    if (tool === 'Glob') {
      return (
        <div className="space-y-2">
          <div className="flex items-center gap-2">
            <span className="text-xs text-dark-500">Pattern:</span>
            <code className="text-xs text-cyan-400 bg-dark-800 px-2 py-0.5 rounded">{input.pattern}</code>
          </div>
          {input.path && (
            <div className="flex items-center gap-2">
              <span className="text-xs text-dark-500">Path:</span>
              <code className="text-xs text-dark-300">{input.path}</code>
            </div>
          )}
        </div>
      );
    }

    if (tool === 'Read') {
      return (
        <div className="space-y-2">
          <div className="flex items-center gap-2">
            <span className="text-xs text-dark-500">File:</span>
            <code className="text-xs text-blue-400">{input.file_path}</code>
          </div>
          {(input.offset || input.limit) && (
            <div className="flex items-center gap-4">
              {input.offset && (
                <div className="flex items-center gap-2">
                  <span className="text-xs text-dark-500">Offset:</span>
                  <code className="text-xs text-dark-300">{input.offset}</code>
                </div>
              )}
              {input.limit && (
                <div className="flex items-center gap-2">
                  <span className="text-xs text-dark-500">Limit:</span>
                  <code className="text-xs text-dark-300">{input.limit}</code>
                </div>
              )}
            </div>
          )}
        </div>
      );
    }

    if (tool === 'TodoWrite' && input.todos) {
      return (
        <div className="space-y-1">
          {input.todos.map((todo, i) => (
            <div key={i} className="flex items-center gap-2 text-xs">
              <span className={`w-2 h-2 rounded-full ${
                todo.status === 'completed' ? 'bg-green-500' :
                todo.status === 'in_progress' ? 'bg-yellow-500' : 'bg-dark-500'
              }`} />
              <span className={todo.status === 'completed' ? 'text-dark-500 line-through' : 'text-dark-300'}>
                {todo.content}
              </span>
            </div>
          ))}
        </div>
      );
    }

    if (tool === 'WebSearch') {
      return (
        <div className="space-y-2">
          <div className="flex items-center gap-2">
            <span className="text-xs text-dark-500">Query:</span>
            <code className="text-xs text-cyan-400 bg-dark-800 px-2 py-0.5 rounded">{input.query}</code>
          </div>
          {input.allowed_domains && input.allowed_domains.length > 0 && (
            <div className="flex items-center gap-2">
              <span className="text-xs text-dark-500">Domains:</span>
              <code className="text-xs text-green-400">{input.allowed_domains.join(', ')}</code>
            </div>
          )}
          {input.blocked_domains && input.blocked_domains.length > 0 && (
            <div className="flex items-center gap-2">
              <span className="text-xs text-dark-500">Blocked:</span>
              <code className="text-xs text-red-400">{input.blocked_domains.join(', ')}</code>
            </div>
          )}
        </div>
      );
    }

    if (tool === 'WebFetch') {
      return (
        <div className="space-y-2">
          <div className="flex items-center gap-2">
            <span className="text-xs text-dark-500">URL:</span>
            <code className="text-xs text-pink-400 bg-dark-800 px-2 py-0.5 rounded truncate max-w-xs">{input.url}</code>
          </div>
          {input.prompt && (
            <div className="space-y-1">
              <span className="text-xs text-dark-500">Prompt:</span>
              <div className="text-xs text-dark-300 bg-dark-800 px-2 py-1 rounded">
                {input.prompt.length > 150 ? input.prompt.substring(0, 150) + '...' : input.prompt}
              </div>
            </div>
          )}
        </div>
      );
    }

    if (tool === 'Task') {
      return (
        <div className="space-y-2">
          {input.subagent_type && (
            <div className="flex items-center gap-2">
              <span className="text-xs text-dark-500">Agent:</span>
              <code className="text-xs text-indigo-400 bg-dark-800 px-2 py-0.5 rounded">{input.subagent_type}</code>
            </div>
          )}
          {input.description && (
            <div className="flex items-center gap-2">
              <span className="text-xs text-dark-500">Task:</span>
              <span className="text-xs text-dark-300">{input.description}</span>
            </div>
          )}
          {input.prompt && (
            <div className="space-y-1">
              <span className="text-xs text-dark-500">Prompt:</span>
              <div className="text-xs text-dark-300 bg-dark-800 px-2 py-1 rounded max-h-24 overflow-y-auto">
                {input.prompt.length > 300 ? input.prompt.substring(0, 300) + '...' : input.prompt}
              </div>
            </div>
          )}
          {input.model && (
            <div className="flex items-center gap-2">
              <span className="text-xs text-dark-500">Model:</span>
              <code className="text-xs text-purple-400">{input.model}</code>
            </div>
          )}
        </div>
      );
    }

    if (tool === 'Write') {
      const fileName = input.file_path?.split('/').pop() || 'file';
      const extension = fileName.split('.').pop() || '';
      const langMap = {
        js: 'javascript', jsx: 'jsx', ts: 'typescript', tsx: 'tsx',
        py: 'python', rb: 'ruby', go: 'go', rs: 'rust',
        json: 'json', yaml: 'yaml', yml: 'yaml', md: 'markdown',
        css: 'css', scss: 'scss', html: 'html', sh: 'bash',
      };
      const language = langMap[extension] || 'text';
      const lines = (input.content || '').split('\n').length;

      return (
        <div className="space-y-2">
          <div className="flex items-center gap-2 text-xs">
            <span className="text-dark-500">File:</span>
            <code className="text-green-400">{input.file_path}</code>
            <span className="text-dark-600">•</span>
            <span className="text-dark-500">{lines} lines</span>
          </div>
          {input.content && (
            <LazyCodeBlock
              language={language}
              style={oneDark}
              customStyle={{ margin: 0, padding: '8px', fontSize: '11px', borderRadius: '4px', maxHeight: '200px' }}
              showLineNumbers={true}
              wrapLongLines={true}
            >
              {input.content}
            </LazyCodeBlock>
          )}
        </div>
      );
    }

    if (tool === 'Skill') {
      return (
        <div className="space-y-2">
          <div className="flex items-center gap-2">
            <Zap className="w-4 h-4 text-purple-400" />
            <span className="text-sm font-medium text-purple-400">{input.skill}</span>
          </div>
        </div>
      );
    }

    if (tool === 'SlashCommand') {
      return (
        <div className="space-y-2">
          <div className="flex items-center gap-2">
            <Command className="w-4 h-4 text-cyan-400" />
            <code className="text-sm text-cyan-400 bg-dark-800 px-2 py-0.5 rounded">{input.command}</code>
          </div>
        </div>
      );
    }

    if (tool === 'AskUserQuestion') {
      const questions = input.questions || [];
      // Only consider it "answered" if there's a successful result (not an error)
      const hasResult = result && !result.isError;

      // Handle option selection
      const handleOptionClick = (qIdx, optIdx, isMulti) => {
        if (hasResult) return; // Already answered
        setSelectedOptions(prev => {
          const key = `q${qIdx}`;
          if (isMulti) {
            const current = prev[key] || [];
            if (current.includes(optIdx)) {
              return { ...prev, [key]: current.filter(i => i !== optIdx) };
            }
            return { ...prev, [key]: [...current, optIdx] };
          }
          return { ...prev, [key]: [optIdx] };
        });
      };

      const isOptionSelected = (qIdx, optIdx) => {
        return (selectedOptions[`q${qIdx}`] || []).includes(optIdx);
      };

      const hasSelection = Object.values(selectedOptions).some(arr => arr.length > 0);

      // Handle submit from CustomInputSection
      const handleCustomSubmit = useCallback((customText) => {
        if (!onSendMessage || hasResult) return;

        if (customText) {
          // Custom text provided
          onSendMessage(customText);
        } else {
          // Use selected options
          const answers = questions.map((q, qIdx) => {
            const selected = selectedOptions[`q${qIdx}`] || [];
            const labels = selected.map(idx => q.options[idx]?.label).filter(Boolean);
            return labels.join(', ') || '';
          }).filter(Boolean);

          if (answers.length > 0) {
            onSendMessage(answers.join('\n'));
          }
        }
      }, [onSendMessage, hasResult, questions, selectedOptions]);

      return (
        <div className="space-y-5">
          {questions.map((q, qIdx) => (
            <div key={qIdx} className="space-y-3">
              {/* Question header */}
              <div className="flex items-center gap-2">
                <span className="px-2.5 py-1 bg-yellow-500/20 text-yellow-400 text-xs font-medium rounded-md">
                  {q.header}
                </span>
                {q.multiSelect && (
                  <span className="text-xs text-dark-500">(select multiple)</span>
                )}
              </div>

              {/* Question text */}
              <p className="text-sm text-dark-200 leading-relaxed">{q.question}</p>

              {/* Options as grid for better layout */}
              <div className="grid gap-2">
                {q.options?.map((opt, optIdx) => {
                  const isSelected = isOptionSelected(qIdx, optIdx);
                  return (
                    <button
                      key={optIdx}
                      onClick={() => handleOptionClick(qIdx, optIdx, q.multiSelect)}
                      disabled={hasResult}
                      className={`w-full flex items-start gap-3 p-3 rounded-lg border text-left
                        transition-all duration-200 ease-out
                        ${hasResult
                          ? 'bg-dark-800/30 border-dark-700 opacity-60 cursor-not-allowed'
                          : isSelected
                            ? 'bg-yellow-500/20 border-yellow-500/50 shadow-lg shadow-yellow-500/10 scale-[1.01]'
                            : 'bg-dark-800/50 border-dark-700 hover:border-yellow-500/30 hover:bg-dark-800 hover:scale-[1.005]'
                        }`}
                    >
                      <div className="mt-0.5 transition-transform duration-200">
                        {q.multiSelect ? (
                          <div className={`w-5 h-5 rounded border-2 flex items-center justify-center transition-all duration-200 ${
                            isSelected ? 'border-yellow-500 bg-yellow-500 scale-110' : 'border-dark-500 bg-dark-700'
                          }`}>
                            {isSelected && <CheckCircle className="w-3.5 h-3.5 text-dark-900" />}
                          </div>
                        ) : (
                          <div className={`w-5 h-5 rounded-full border-2 flex items-center justify-center transition-all duration-200 ${
                            isSelected ? 'border-yellow-500 bg-yellow-500 scale-110' : 'border-dark-500 bg-dark-700'
                          }`}>
                            {isSelected && <div className="w-2.5 h-2.5 rounded-full bg-dark-900" />}
                          </div>
                        )}
                      </div>
                      <div className="flex-1 min-w-0">
                        <div className={`text-sm font-medium transition-colors duration-200 ${isSelected ? 'text-yellow-300' : 'text-dark-200'}`}>
                          {opt.label}
                        </div>
                        {opt.description && (
                          <div className="text-xs text-dark-500 mt-1 leading-relaxed">{opt.description}</div>
                        )}
                      </div>
                    </button>
                  );
                })}
              </div>
            </div>
          ))}

          {/* Custom input + Submit section - isolated to prevent re-renders */}
          {!hasResult && onSendMessage && (
            <CustomInputSection onSubmit={handleCustomSubmit} hasSelection={hasSelection} />
          )}

          {hasResult && (
            <div className="flex items-center gap-2 pt-3 border-t border-dark-700 text-sm text-green-400">
              <CheckCircle className="w-4 h-4" />
              <span>Response submitted</span>
            </div>
          )}
        </div>
      );
    }

    // Default JSON view
    return (
      <LazyCodeBlock
        language="json"
        style={oneDark}
        customStyle={{ margin: 0, padding: '8px', fontSize: '11px', borderRadius: '4px' }}
      >
        {formatInput()}
      </LazyCodeBlock>
    );
  };

  // Detect if result content looks like code
  const resultLooksLikeCode = resultData?.contentStr && (
    resultData.contentStr.includes('function ') ||
    resultData.contentStr.includes('const ') ||
    resultData.contentStr.includes('import ') ||
    resultData.contentStr.includes('export ') ||
    resultData.contentStr.startsWith('{') ||
    resultData.contentStr.startsWith('[')
  );

  // Interactive tools like AskUserQuestion need more space
  const isInteractiveTool = config.isInteractive;
  const cardWidthClass = isInteractiveTool ? 'w-full max-w-2xl' : 'inline-block max-w-[85%]';
  const contentHeightClass = isInteractiveTool ? '' : 'max-h-48 overflow-y-auto';

  return (
    <div className={`ml-11 message-enter rounded-lg border ${colors.border} ${colors.bg} overflow-hidden transition-all duration-200 hover:shadow-lg ${colors.glow} ${cardWidthClass}`}>
      {/* Header */}
      <div className="flex items-center gap-3 p-2.5">
        {/* Icon */}
        <div className={`w-7 h-7 rounded-md ${colors.bg} border ${colors.border} flex items-center justify-center flex-shrink-0`}>
          <Icon className={`w-4 h-4 ${colors.text}`} />
        </div>

        {/* Tool info */}
        <div className="flex-1 min-w-0">
          <div className="flex items-center gap-2">
            <span className={`text-xs font-medium ${colors.text}`}>{config.label}</span>
            <span className="text-dark-600">•</span>
            <code className="text-xs text-dark-300 truncate">{summary}</code>

            {/* Result badge - hide for interactive tools since they handle their own state */}
            {resultData && !isInteractiveTool && (
              <>
                <span className="text-dark-600">•</span>
                <span className={`inline-flex items-center gap-1 text-xs ${resultData.isSuccess ? 'text-green-400' : 'text-red-400'}`}>
                  {resultData.isSuccess ? (
                    <CheckCircle className="w-3 h-3" />
                  ) : (
                    <AlertCircle className="w-3 h-3" />
                  )}
                  {resultData.isSuccess ? 'OK' : 'Error'}
                </span>
              </>
            )}
          </div>
        </div>
      </div>

      {/* Content - interactive tools get full height, others are capped */}
      <div className={`border-t border-dark-700/50 p-3 bg-dark-900/50 overflow-x-auto ${contentHeightClass}`}>
        {renderSpecialInput()}
      </div>

      {/* Collapsible Result Section - hide for interactive tools */}
      {resultData && !isInteractiveTool && (
        <div className="border-t border-dark-700/50">
          <button
            onClick={() => setShowResult(!showResult)}
            className={`w-full flex items-center gap-2 px-3 py-2 text-xs transition-colors
              ${resultData.isSuccess
                ? 'bg-green-500/5 hover:bg-green-500/10 text-green-400'
                : 'bg-red-500/5 hover:bg-red-500/10 text-red-400'
              }`}
          >
            {showResult ? <ChevronDown className="w-3 h-3" /> : <ChevronRight className="w-3 h-3" />}
            <span>Result</span>
            <span className="text-dark-500">({resultData.chars} chars)</span>
            {resultData.systemReminders.length > 0 && (
              <span className="text-purple-400 ml-auto">{resultData.systemReminders.length} hint{resultData.systemReminders.length > 1 ? 's' : ''}</span>
            )}
          </button>

          {showResult && (
            <div className={`p-3 ${resultData.isSuccess ? 'bg-green-500/5' : 'bg-red-500/5'}`}>
              {/* System Reminders */}
              {resultData.systemReminders.length > 0 && (
                <div className="mb-2 pb-2 border-b border-purple-500/20">
                  {resultData.systemReminders.map((reminder, idx) => (
                    <div key={idx} className="text-xs text-purple-300/70 font-mono whitespace-pre-wrap mb-1 last:mb-0">
                      <span className="text-purple-400 font-semibold">Hint {idx + 1}:</span>
                      <div className="mt-0.5 pl-2 border-l-2 border-purple-500/30 max-h-20 overflow-y-auto">
                        {reminder.length > 200 ? reminder.substring(0, 200) + '...' : reminder}
                      </div>
                    </div>
                  ))}
                </div>
              )}

              {/* Result Content */}
              <div className="max-h-48 overflow-y-auto">
                {resultLooksLikeCode ? (
                  <LazyCodeBlock
                    language="javascript"
                    style={oneDark}
                    customStyle={{ margin: 0, padding: '8px', fontSize: '11px', background: 'transparent' }}
                    wrapLongLines={true}
                  >
                    {resultData.contentStr}
                  </LazyCodeBlock>
                ) : (
                  <pre className="text-xs text-dark-400 whitespace-pre-wrap font-mono">{resultData.contentStr}</pre>
                )}
              </div>
            </div>
          )}
        </div>
      )}
    </div>
  );
});

const ToolResultCard = memo(function ToolResultCard({ content, isSuccess = true }) {
  const [showSystemInfo, setShowSystemInfo] = useState(false);

  // Memoize parsed content
  const { rawContent, contentStr, systemReminders } = useMemo(() => {
    let raw = '';
    if (content === undefined || content === null) {
      raw = '(no content)';
    } else if (typeof content === 'string') {
      raw = content;
    } else if (Array.isArray(content)) {
      raw = content.map(c => {
        if (typeof c === 'string') return c;
        if (c?.type === 'text') return c.text || '';
        return JSON.stringify(c);
      }).join('\n');
    } else {
      raw = JSON.stringify(content, null, 2);
    }
    const parsed = parseSystemReminders(raw);
    return { rawContent: raw, contentStr: parsed.content, systemReminders: parsed.reminders };
  }, [content]);

  const lines = contentStr.split('\n').length;
  const chars = contentStr.length;

  // Detect if content looks like code or command output
  const looksLikeCode = contentStr.includes('function ') ||
                        contentStr.includes('const ') ||
                        contentStr.includes('import ') ||
                        contentStr.includes('export ') ||
                        contentStr.startsWith('{') ||
                        contentStr.startsWith('[');

  return (
    <div className={`ml-11 message-enter rounded-lg border overflow-hidden transition-all duration-200 inline-block max-w-[85%]
      ${isSuccess ? 'border-green-500/30 bg-green-500/10' : 'border-red-500/30 bg-red-500/10'}`}>
      {/* Header */}
      <div className="flex items-center gap-3 p-2.5">
        <div className={`w-7 h-7 rounded-md flex items-center justify-center flex-shrink-0
          ${isSuccess ? 'bg-green-500/20 border border-green-500/30' : 'bg-red-500/20 border border-red-500/30'}`}>
          {isSuccess ? (
            <CheckCircle className="w-4 h-4 text-green-400" />
          ) : (
            <AlertCircle className="w-4 h-4 text-red-400" />
          )}
        </div>

        <div className="flex-1 min-w-0">
          <div className="flex items-center gap-2">
            <span className={`text-xs font-medium ${isSuccess ? 'text-green-400' : 'text-red-400'}`}>
              {isSuccess ? 'Success' : 'Error'}
            </span>
            <span className="text-dark-600">•</span>
            <span className="text-xs text-dark-500">{lines} lines, {chars} chars</span>
            {systemReminders.length > 0 && (
              <>
                <span className="text-dark-600">•</span>
                <button
                  onClick={() => setShowSystemInfo(!showSystemInfo)}
                  className="flex items-center gap-1 text-xs text-purple-400 hover:text-purple-300 transition-colors"
                >
                  <Info className="w-3 h-3" />
                  <span>{systemReminders.length} system hint{systemReminders.length > 1 ? 's' : ''}</span>
                  {showSystemInfo ? <ChevronDown className="w-3 h-3" /> : <ChevronRight className="w-3 h-3" />}
                </button>
              </>
            )}
          </div>
        </div>
      </div>

      {/* System Reminders - collapsible */}
      {showSystemInfo && systemReminders.length > 0 && (
        <div className="border-t border-purple-500/20 bg-purple-900/10 p-2.5">
          {systemReminders.map((reminder, idx) => (
            <div key={idx} className="text-xs text-purple-300/70 font-mono whitespace-pre-wrap mb-2 last:mb-0">
              <span className="text-purple-400 font-semibold">System Hint {idx + 1}:</span>
              <div className="mt-1 pl-2 border-l-2 border-purple-500/30 max-h-32 overflow-y-auto">
                {reminder}
              </div>
            </div>
          ))}
        </div>
      )}

      {/* Content - always visible with max height and scroll */}
      {contentStr && (
        <div className="border-t border-dark-700/50 bg-dark-900/50 max-h-48 overflow-y-auto">
          {looksLikeCode ? (
            <LazyCodeBlock
              language="javascript"
              style={oneDark}
              customStyle={{ margin: 0, padding: '12px', fontSize: '11px', background: 'transparent' }}
              wrapLongLines={true}
            >
              {contentStr}
            </LazyCodeBlock>
          ) : (
            <pre className="text-xs text-dark-400 whitespace-pre-wrap p-3 font-mono">{contentStr}</pre>
          )}
        </div>
      )}
    </div>
  );
});
