"use client";
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import { cn } from "@stigmer/theme";
import { formatDuration } from "./ToolCallDetail";
import { humanizeToolName } from "./tool-categories";
import { CollapsiblePre, CollapsibleJsonBlock, McpServerIcon, formatJson, isScalar, humanizeArgKey, } from "./tool-rendering-primitives";
/**
 * MCP-aware detail renderer for tool calls originating from an MCP
 * server.
 *
 * Replaces the generic "dump args + result as raw JSON" fallback
 * with structured formatting:
 *
 * - **Arguments** are rendered as a labelled key-value list.
 *   Scalars display inline; objects/arrays collapse into formatted
 *   JSON blocks.
 * - **Results** are parsed through {@link parseMcpResult} which
 *   handles MCP content-block arrays, embedded JSON, and Python
 *   repr artefacts before rendering.
 *
 * @example
 * ```tsx
 * <McpToolDetail toolCall={toolCall} />
 * ```
 */
export function McpToolDetail({ toolCall, className }) {
    const duration = formatDuration(toolCall.startedAt, toolCall.completedAt);
    return (_jsxs("div", { className: cn("space-y-3 text-xs", className), children: [_jsx(McpMetadataRow, { mcpServerSlug: toolCall.mcpServerSlug, toolName: toolCall.name, duration: duration }), toolCall.args && Object.keys(toolCall.args).length > 0 && (_jsx(McpArgsView, { args: toolCall.args })), toolCall.result && (_jsx(McpResultView, { result: toolCall.result }))] }));
}
/**
 * Displays MCP server slug, tool name, and optional duration as a
 * compact metadata row above tool arguments.
 */
export function McpMetadataRow({ mcpServerSlug, toolName, duration, }) {
    const hasMetadata = mcpServerSlug || duration;
    if (!hasMetadata)
        return null;
    return (_jsxs("div", { className: "flex flex-wrap items-center gap-x-3 gap-y-1 text-muted-foreground", children: [mcpServerSlug && (_jsxs("span", { className: "inline-flex items-center gap-1.5 rounded bg-muted px-1.5 py-0.5 font-mono", children: [_jsx(McpServerIcon, {}), mcpServerSlug, _jsx("span", { className: "text-muted-foreground-subtle", children: "/" }), _jsx("span", { className: "text-foreground", children: humanizeToolName(toolName) })] })), duration && _jsx("span", { children: duration })] }));
}
/**
 * Renders MCP tool arguments as a structured key-value list.
 *
 * Scalars display inline; objects and arrays collapse into
 * formatted JSON blocks via {@link CollapsibleJsonBlock}.
 */
export function McpArgsView({ args }) {
    const entries = Object.entries(args);
    if (entries.length === 0)
        return null;
    const scalars = [];
    const complex = [];
    for (const [key, value] of entries) {
        if (isScalar(value)) {
            scalars.push([key, String(value)]);
        }
        else {
            complex.push([key, value]);
        }
    }
    return (_jsxs("div", { className: "space-y-2", children: [_jsx("span", { className: "font-medium text-muted-foreground", children: "Arguments" }), scalars.length > 0 && (_jsx("dl", { className: "grid grid-cols-[auto_1fr] gap-x-3 gap-y-1 rounded-md border border-border bg-muted-faint px-2.5 py-2", children: scalars.map(([key, value]) => (_jsx(ScalarRow, { label: key, value: value }, key))) })), complex.map(([key, value]) => (_jsx(CollapsibleJsonBlock, { label: humanizeArgKey(key), content: formatJson(value) }, key)))] }));
}
function ScalarRow({ label, value }) {
    const isMultiline = value.includes("\n");
    return (_jsxs(_Fragment, { children: [_jsx("dt", { className: "whitespace-nowrap font-mono text-muted-foreground", children: humanizeArgKey(label) }), isMultiline ? (_jsx("dd", { className: "min-w-0", children: _jsx("pre", { className: "whitespace-pre-wrap break-words rounded border border-border bg-muted-subtle px-2 py-1 font-mono text-foreground", children: value }) })) : (_jsx("dd", { className: "min-w-0 truncate font-mono text-foreground", title: value, children: value }))] }));
}
// ---------------------------------------------------------------------------
// Result — intelligent parsing
// ---------------------------------------------------------------------------
function McpResultView({ result }) {
    const parsed = parseMcpResult(result);
    return (_jsxs("div", { className: "space-y-1", children: [_jsx("span", { className: "font-medium text-muted-foreground", children: "Result" }), _jsx(CollapsiblePre, { content: parsed, className: "max-h-80 overflow-auto rounded-md border border-border bg-muted-subtle p-2 text-foreground" })] }));
}
/**
 * Extracts human-readable content from an MCP tool result string.
 *
 * Handles three common formats that arrive from the backend:
 *
 * 1. **MCP content-block array** — `[{"type":"text","text":"..."}]`.
 *    Text parts are extracted and, if they are themselves valid
 *    JSON, pretty-printed.
 * 2. **Python repr** — `[{'type': 'text', 'text': '...'}]`. Single
 *    quotes are normalised to double quotes before parsing.
 * 3. **Plain JSON / text** — returned formatted when valid JSON,
 *    or as-is otherwise.
 */
export function parseMcpResult(result) {
    const trimmed = result.trim();
    // Fast path: try standard JSON parse first.
    const jsonParsed = tryParseJson(trimmed);
    if (jsonParsed !== undefined) {
        const extracted = tryExtractContentBlocks(jsonParsed);
        if (extracted !== null)
            return extracted;
        return JSON.stringify(jsonParsed, null, 2);
    }
    // Attempt to fix Python repr (single-quoted dicts/lists).
    const fixed = tryFixPythonRepr(trimmed);
    if (fixed !== undefined) {
        const extracted = tryExtractContentBlocks(fixed);
        if (extracted !== null)
            return extracted;
        return JSON.stringify(fixed, null, 2);
    }
    return trimmed;
}
function isMcpContentBlockArray(val) {
    if (!Array.isArray(val))
        return false;
    if (val.length === 0)
        return false;
    return val.every((item) => typeof item === "object" &&
        item !== null &&
        "type" in item &&
        typeof item.type === "string");
}
function tryExtractContentBlocks(parsed) {
    if (!isMcpContentBlockArray(parsed))
        return null;
    const textParts = [];
    for (const block of parsed) {
        if (block.type === "text" && typeof block.text === "string") {
            const innerJson = tryParseJson(block.text.trim());
            if (innerJson !== undefined) {
                textParts.push(JSON.stringify(innerJson, null, 2));
            }
            else {
                textParts.push(block.text);
            }
        }
    }
    return textParts.length > 0 ? textParts.join("\n\n") : null;
}
// ---------------------------------------------------------------------------
// JSON / Python repr helpers
// ---------------------------------------------------------------------------
function tryParseJson(str) {
    try {
        return JSON.parse(str);
    }
    catch {
        return undefined;
    }
}
/**
 * Attempts to convert a Python repr string (single-quoted
 * dicts/lists with True/False/None) into a parsed JS value.
 *
 * This is intentionally conservative: it only handles the
 * most common patterns and bails on ambiguity.
 */
function tryFixPythonRepr(str) {
    if (!str.startsWith("[") && !str.startsWith("{"))
        return undefined;
    let fixed = str
        .replace(/'/g, '"')
        .replace(/\bTrue\b/g, "true")
        .replace(/\bFalse\b/g, "false")
        .replace(/\bNone\b/g, "null");
    // Handle trailing commas before ] or } (common in Python repr).
    fixed = fixed.replace(/,\s*([}\]])/g, "$1");
    return tryParseJson(fixed);
}
//# sourceMappingURL=McpToolDetail.js.map