/**
 * Routes content blocks to type-specific renderers.
 *
 * Pairs tool_use + tool_result blocks into MergedToolBlock components
 * using a pre-built resultMap for O(1) lookup. Orphaned tool_result
 * blocks (no matching tool_use) fall back to standalone ToolResultBlock.
 *
 * @exports ContentBlockRenderer — The routing component
 */

import type { ContentBlock, ToolResultContent, EscalationContent } from '../../../types';
import { MarkdownRenderer, AskUserQuestion } from '../../../components/common';
import { MergedToolBlock } from './MergedToolBlock';
import { ToolResultBlock } from './ToolResultBlock';
import { InlinePermissionRequest } from './InlinePermissionRequest';
import { EscalationBlock } from './EscalationBlock';

interface ContentBlockRendererProps {
  block: ContentBlock;
  /** Pre-built map from toolUseId → ToolResultContent for O(1) pairing. */
  resultMap: Map<string, ToolResultContent>;
  /** Full content array for orphaned tool_result check. */
  allBlocks: ContentBlock[];
  onAnswerQuestion?: (toolUseId: string, answers: Record<string, string>) => void;
  /** Callback when user approves/denies a permission request. */
  onPermissionDecision?: (requestId: string, decision: 'approve' | 'deny') => void;
  /** Callback when user clicks an escalation option — sends as chat response. */
  onEscalationSelect?: (escalationId: string, optionLabel: string) => void;
  pendingToolUseId?: string;
  /** The request ID of the currently pending permission (buttons enabled for this one). */
  pendingPermissionRequestId?: string;
  isStreaming?: boolean;
  /** The ID of the last tool_use block without a result — only this one gets a spinner. */
  lastPendingToolUseId?: string | null;
}

export function ContentBlockRenderer({
  block,
  resultMap,
  allBlocks,
  onAnswerQuestion,
  onPermissionDecision,
  onEscalationSelect,
  pendingToolUseId,
  pendingPermissionRequestId,
  isStreaming,
  lastPendingToolUseId,
}: ContentBlockRendererProps) {
  if (block.type === 'text') {
    return <MarkdownRenderer content={block.text || ''} />;
  }

  if (block.type === 'tool_use') {
    // Pair with matching tool_result via resultMap (O(1))
    const matchingResult = resultMap.get(block.id);

    return (
      <MergedToolBlock
        name={block.name || 'Unknown'}
        summary={block.summary || ''}
        toolUseId={block.id}
        category={block.category}
        resultContent={matchingResult?.content}
        resultTruncated={matchingResult?.truncated}
        resultIsError={matchingResult?.isError}
        isPending={lastPendingToolUseId != null ? block.id === lastPendingToolUseId : (!matchingResult && !!isStreaming)}
        isStreaming={isStreaming}
      />
    );
  }

  if (block.type === 'tool_result') {
    // Skip if already consumed by a MergedToolBlock
    const hasMatchingToolUse = allBlocks.some(
      (b) => b.type === 'tool_use' && b.id === block.toolUseId,
    );
    if (hasMatchingToolUse) return null;

    // Orphaned tool_result — standalone fallback
    return (
      <ToolResultBlock
        content={block.content}
        isError={block.isError}
        truncated={block.truncated ?? false}
      />
    );
  }

  if (block.type === 'ask_user_question') {
    const isPending = pendingToolUseId === block.toolUseId;
    const isAnswered = !isPending && !isStreaming;

    return (
      <AskUserQuestion
        questions={block.questions}
        toolUseId={block.toolUseId}
        onSubmit={onAnswerQuestion || (() => {})}
        disabled={isAnswered || !!isStreaming}
      />
    );
  }

  if (block.type === 'cmd_permission_request') {
    return (
      <InlinePermissionRequest
        requestId={block.requestId}
        toolName={block.toolName}
        toolInput={block.toolInput}
        reason={block.reason}
        isPending={pendingPermissionRequestId === block.requestId}
        decision={block.decision}
        onDecision={onPermissionDecision}
      />
    );
  }

  if (block.type === 'escalation') {
    const esc = block as EscalationContent;
    return (
      <EscalationBlock
        id={esc.id}
        severity={esc.severity}
        reason={esc.reason}
        options={esc.options || []}
        status={esc.status}
        resolution={esc.resolution}
        onSelectOption={esc.status === 'pending' ? onEscalationSelect : undefined}
      />
    );
  }

  if (block.type === 'thinking') {
    const thinkingText = (block as { thinking?: string }).thinking || '';
    if (!thinkingText) return null;
    return (
      <details open className="group border border-[var(--color-border)] rounded-lg overflow-hidden text-sm">
        <summary className="px-3 py-2 cursor-pointer bg-[var(--color-card)] text-[var(--color-text-muted)] hover:text-[var(--color-text)] select-none flex items-center gap-1.5">
          <span className="text-xs">💭</span>
          <span>Thinking</span>
          <span className="ml-auto text-xs opacity-60">{thinkingText.length > 200 ? `~${Math.ceil(thinkingText.length / 4)} tokens` : ''}</span>
        </summary>
        <div className="px-3 py-2 border-t border-[var(--color-border)] bg-[var(--color-bg)] text-[var(--color-text-muted)] italic text-xs leading-relaxed whitespace-pre-wrap max-h-64 overflow-y-auto">
          {thinkingText}
        </div>
      </details>
    );
  }

  return null;
}
