import Markdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import type { Message, ToolResult } from '@/api/types';
import { Wrench, AlertCircle, Loader2 } from 'lucide-react';
import { AskUserInputCard } from './AskUserInputCard';

interface Props {
  message: Message;
  chatId: string;
  toolResultsMap: Record<string, ToolResult>;
}

export function MessageBubble({ message, chatId }: Props) {
  if (message.role === 'tool') {
    return <ToolResultBubble message={message} />;
  }

  const isUser = message.role === 'user';
  const isStreaming = message.status === 'streaming';
  const isFailed = message.status === 'failed';

  return (
    <div className={`flex ${isUser ? 'justify-end' : 'justify-start'} mb-3`}>
      <div
        className={`max-w-[85%] rounded-lg px-4 py-2.5 ${
          isUser
            ? 'bg-blue-600 text-white'
            : 'bg-zinc-800 text-zinc-100 border border-zinc-700'
        }`}
      >
        {isFailed && (
          <div className="flex items-center gap-1.5 text-red-400 text-xs mb-1">
            <AlertCircle size={12} />
            <span>Failed</span>
          </div>
        )}

        {message.tool_calls && message.tool_calls.length > 0 && (
          <div className="mb-2 space-y-1">
            {message.tool_calls.map((tc) => {
              if (tc.name === 'ask_user_input') {
                const result = message.tool_results ?? null;
                return (
                  <AskUserInputCard
                    key={tc.id}
                    toolCall={tc}
                    toolResult={result}
                    chatId={chatId}
                  />
                );
              }
              return (
                <div
                  key={tc.id}
                  className="flex items-center gap-1.5 text-xs text-zinc-400 bg-zinc-900/50 rounded px-2 py-1"
                >
                  <Wrench size={11} />
                  <span className="font-mono">{tc.name}</span>
                  <span className="text-zinc-500 truncate max-w-[200px]">
                    {truncateArgs(tc.args)}
                  </span>
                </div>
              );
            })}
          </div>
        )}

        {message.content.trim() && (
          <div className="prose prose-invert prose-sm max-w-none [&_pre]:bg-zinc-900 [&_pre]:p-3 [&_pre]:rounded [&_pre]:overflow-x-auto [&_code]:text-zinc-300 [&_p]:my-1.5">
            <Markdown remarkPlugins={[remarkGfm]}>{message.content}</Markdown>
          </div>
        )}

        {isStreaming && !message.content.trim() && (
          <div className="flex items-center gap-1.5 text-zinc-400">
            <Loader2 size={14} className="animate-spin" />
            <span className="text-xs">Thinking...</span>
          </div>
        )}

        {isStreaming && message.content.trim() && (
          <span className="inline-block w-1.5 h-4 bg-zinc-400 animate-pulse ml-0.5 align-middle" />
        )}
      </div>
    </div>
  );
}

function ToolResultBubble({ message }: { message: Message }) {
  const result = message.tool_results;
  if (!result) return null;

  const isError = result.error;
  const output = result.output != null ? String(result.output) : '';
  const displayOutput =
    output.length > 300 ? output.slice(0, 300) + '...' : output;

  return (
    <div className="flex justify-start mb-2 ml-6">
      <div
        className={`max-w-[80%] rounded px-3 py-2 text-xs font-mono border ${
          isError
            ? 'bg-red-950/30 border-red-800/50 text-red-300'
            : 'bg-zinc-800/50 border-zinc-700/50 text-zinc-400'
        }`}
      >
        {result.truncated && (
          <span className="text-yellow-500 text-[10px] block mb-1">
            [truncated]
          </span>
        )}
        <pre className="whitespace-pre-wrap break-all">{displayOutput}</pre>
      </div>
    </div>
  );
}

function truncateArgs(args: unknown): string {
  if (!args) return '';
  try {
    if (typeof args === 'object' && args !== null) {
      const obj = args as Record<string, unknown>;
      const keys = Object.keys(obj);
      if (keys.length === 0) return '';
      const first = keys[0]!;
      const val = String(obj[first] ?? '');
      const display = val.length > 40 ? val.slice(0, 40) + '...' : val;
      return `${first}: ${display}`;
    }
    const str = String(args);
    return str.length > 50 ? str.slice(0, 50) + '...' : str;
  } catch {
    return String(args).length > 50 ? String(args).slice(0, 50) + '...' : String(args);
  }
}
