import { getToolUiResourceUri } from "@modelcontextprotocol/ext-apps/app-bridge";
import { formatToolName, isToolExcluded } from "./types.js";
import { resourceNameToToolName } from "./resource-tools.js";
import { extractToolUiStreamMode } from "./utils.js";
export function buildToolMetadata(tools, resources, definition, serverName, prefix) {
    const metadata = [];
    const failedTools = [];
    for (const tool of tools) {
        if (!tool?.name) {
            failedTools.push("(unnamed)");
            continue;
        }
        if (isToolExcluded(tool.name, serverName, prefix, definition.excludeTools)) {
            continue;
        }
        let uiResourceUri;
        try {
            uiResourceUri = getToolUiResourceUri({ _meta: tool._meta });
        }
        catch {
            failedTools.push(tool.name);
        }
        metadata.push({
            name: formatToolName(tool.name, serverName, prefix),
            originalName: tool.name,
            description: tool.description ?? "",
            inputSchema: tool.inputSchema,
            uiResourceUri,
            uiStreamMode: extractToolUiStreamMode(tool._meta),
        });
    }
    if (definition.exposeResources !== false) {
        for (const resource of resources) {
            const baseName = `get_${resourceNameToToolName(resource.name)}`;
            if (isToolExcluded(baseName, serverName, prefix, definition.excludeTools)) {
                continue;
            }
            metadata.push({
                name: formatToolName(baseName, serverName, prefix),
                originalName: baseName,
                description: resource.description ?? `Read resource: ${resource.uri}`,
                resourceUri: resource.uri,
            });
        }
    }
    return { metadata, failedTools };
}
export function getToolNames(state, serverName) {
    return state.toolMetadata.get(serverName)?.map(m => m.name) ?? [];
}
export function totalToolCount(state) {
    let count = 0;
    for (const metadata of state.toolMetadata.values()) {
        count += metadata.length;
    }
    return count;
}
export function findToolByName(metadata, toolName) {
    if (!metadata)
        return undefined;
    const exact = metadata.find(m => m.name === toolName);
    if (exact)
        return exact;
    const normalized = toolName.replace(/-/g, "_");
    return metadata.find(m => m.name.replace(/-/g, "_") === normalized);
}
export function formatSchema(schema, indent = "  ") {
    if (!schema || typeof schema !== "object") {
        return `${indent}(no schema)`;
    }
    const s = schema;
    if (s.type === "object" && s.properties && typeof s.properties === "object") {
        const props = s.properties;
        const required = Array.isArray(s.required) ? s.required : [];
        if (Object.keys(props).length === 0) {
            return `${indent}(no parameters)`;
        }
        const lines = [];
        for (const [name, propSchema] of Object.entries(props)) {
            const isRequired = required.includes(name);
            const propLine = formatProperty(name, propSchema, isRequired, indent);
            lines.push(propLine);
        }
        return lines.join("\n");
    }
    if (s.type) {
        return `${indent}(${s.type})`;
    }
    return `${indent}(complex schema)`;
}
function formatProperty(name, schema, required, indent) {
    if (!schema || typeof schema !== "object") {
        return `${indent}${name}${required ? " *required*" : ""}`;
    }
    const s = schema;
    const parts = [];
    let typeStr = "";
    if (s.type) {
        if (Array.isArray(s.type)) {
            typeStr = s.type.join(" | ");
        }
        else {
            typeStr = String(s.type);
        }
    }
    else if (s.enum) {
        typeStr = "enum";
    }
    else if (s.anyOf || s.oneOf) {
        typeStr = "union";
    }
    if (Array.isArray(s.enum)) {
        const enumVals = s.enum.map(v => JSON.stringify(v)).join(", ");
        typeStr = `enum: ${enumVals}`;
    }
    parts.push(`${indent}${name}`);
    if (typeStr)
        parts.push(`(${typeStr})`);
    if (required)
        parts.push("*required*");
    if (s.description && typeof s.description === "string") {
        parts.push(`- ${s.description}`);
    }
    if (s.default !== undefined) {
        parts.push(`[default: ${JSON.stringify(s.default)}]`);
    }
    return parts.join(" ");
}
