import { guardAccepted, isJsonObject, optionalTrimmedString } from "../../_shared/baseToolAdapter.js";
import { createMcpToolRegistryAuditEvent, createMcpToolRegistryFailure, ensureMcpToolRegistryPermissions, ensureMcpToolRegistryScope, mcpRegisterToolDescriptor, normalizeMcpServerId, normalizeMcpToolName, policyFailure, } from "../mcp.registerTool/core.js";
export const mcpUnregisterToolDescriptor = {
    toolId: "mcp.unregisterTool",
    capability: "unregister-mcp-tool",
    route: "agent_executionEngine.basic_toolLayer.baseTools.mcpBase.tool",
    permissionsRequired: mcpRegisterToolDescriptor.permissionsRequired,
    defaultDryRun: true,
    unsafeSideEffects: true,
    tapOwnsApproval: true,
    runtimeOwnsMcpClient: true,
    providerBoundary: "BaseToolExecutorPort.mcp.unregisterTool",
};
function normalizeContext(value) {
    if (value === undefined)
        return {};
    if (!isJsonObject(value))
        return { ok: false, code: "INVALID_CONTEXT", message: "mcp.unregisterTool context must be a JSON object.", boundary: "input" };
    const base = value;
    return {
        ...base,
        serverId: optionalTrimmedString(base.serverId),
        invocationId: optionalTrimmedString(base.invocationId),
        runtimeId: optionalTrimmedString(base.runtimeId),
        sessionId: optionalTrimmedString(base.sessionId),
    };
}
function validate(request) {
    const root = request === undefined ? {} : request;
    if (!isJsonObject(root))
        return { ok: false, code: "INVALID_REQUEST", message: "mcp.unregisterTool request must be a JSON object.", boundary: "input" };
    const context = normalizeContext(root.context);
    if ("ok" in context)
        return context;
    if (root.target !== undefined && root.target !== null && !isJsonObject(root.target))
        return { ok: false, code: "MISSING_SERVER_ID", message: "mcp.unregisterTool requires target.serverId or context.serverId", boundary: "input", context };
    const target = isJsonObject(root.target) ? root.target : {};
    const serverId = normalizeMcpServerId("mcp.unregisterTool", target.serverId, context);
    if (typeof serverId !== "string")
        return serverId;
    const toolName = normalizeMcpToolName("mcp.unregisterTool", target.toolName, context, serverId);
    if (typeof toolName !== "string")
        return toolName;
    const scope = ensureMcpToolRegistryScope("mcp.unregisterTool", serverId, context);
    if (scope !== undefined)
        return scope;
    const permissions = ensureMcpToolRegistryPermissions("mcp.unregisterTool", mcpUnregisterToolDescriptor.permissionsRequired, context, serverId);
    if (permissions !== undefined)
        return permissions;
    return { ok: true, target: { serverId, toolName, keepAuditRecord: target.keepAuditRecord !== false }, context, acceptedScopes: context.requestedScopes ?? [] };
}
function auditEvent(type, dryRun, context, serverId, metadata) {
    return createMcpToolRegistryAuditEvent("mcp.unregisterTool", type, { ...context, dryRun }, serverId, metadata);
}
function envelope(target, result) {
    return {
        toolName: result?.toolName ?? target.toolName,
        state: result?.status ?? "planned",
        keepAuditRecord: target.keepAuditRecord !== false,
        source: result === undefined ? "mockable-envelope" : "runtime-provider",
    };
}
function output(normalized, options) {
    return {
        kind: "agentCore.basicTool.mcp.unregisterTool",
        target: normalized.target,
        dryRun: options.dryRun,
        executionBlocked: options.dryRun,
        providerCalled: options.providerCalled,
        permissionsRequired: mcpUnregisterToolDescriptor.permissionsRequired,
        unsafeSideEffects: true,
        acceptedScopes: normalized.acceptedScopes,
        registryEnvelope: envelope(normalized.target, options.result),
        providerMetadata: options.result?.providerMetadata,
    };
}
export function planMcpToolUnregistration(request = {}) {
    const normalized = validate(request);
    if (!normalized.ok) {
        if ("error" in normalized)
            return normalized;
        return createMcpToolRegistryFailure("mcp.unregisterTool", normalized.code, normalized.message, normalized.boundary, normalized.context);
    }
    const blocked = policyFailure("mcp.unregisterTool", normalized.context, normalized.target.serverId);
    if (blocked !== undefined)
        return blocked;
    if (normalized.context.dryRun === false)
        return createMcpToolRegistryFailure("mcp.unregisterTool", "REAL_EXECUTION_BLOCKED", "mcp.unregisterTool only returns a guarded dry-run plan through plan* helpers", "contract", normalized.context, normalized.target.serverId);
    return { ok: true, toolId: "mcp.unregisterTool", output: output(normalized, { dryRun: true, providerCalled: false }), audit: [auditEvent("agentCore.basicTool.mcp.unregisterTool.dryRun", true, normalized.context, normalized.target.serverId, { toolName: normalized.target.toolName, keepAuditRecord: normalized.target.keepAuditRecord })], events: ["basicTool.mcp.unregisterTool.dryRun"] };
}
export async function executeMcpToolUnregistration(request = {}, provider) {
    const normalized = validate(request);
    if (!normalized.ok) {
        if ("error" in normalized)
            return normalized;
        return createMcpToolRegistryFailure("mcp.unregisterTool", normalized.code, normalized.message, normalized.boundary, normalized.context);
    }
    const blocked = policyFailure("mcp.unregisterTool", normalized.context, normalized.target.serverId);
    if (blocked !== undefined)
        return blocked;
    if (normalized.context.dryRun !== false)
        return { ok: true, toolId: "mcp.unregisterTool", output: output(normalized, { dryRun: true, providerCalled: false }), audit: [auditEvent("agentCore.basicTool.mcp.unregisterTool.dryRun", true, normalized.context, normalized.target.serverId, { toolName: normalized.target.toolName, keepAuditRecord: normalized.target.keepAuditRecord })], events: ["basicTool.mcp.unregisterTool.dryRun"] };
    if (!guardAccepted(normalized.context.guard))
        return createMcpToolRegistryFailure("mcp.unregisterTool", "GOVERNANCE_REJECTED", "mcp.unregisterTool requires an accepted runtime guard before real dispatch.", "governance", normalized.context, normalized.target.serverId);
    if (provider === undefined)
        return createMcpToolRegistryFailure("mcp.unregisterTool", "PROVIDER_UNAVAILABLE", "Runtime MCP unregisterTool provider is unavailable.", "provider", normalized.context, normalized.target.serverId, "basicTool.mcp.unregisterTool.providerUnavailable");
    try {
        const result = await provider(normalized.target, { runtimeId: normalized.context.runtimeId, sessionId: normalized.context.sessionId, invocationId: normalized.context.invocationId, auditMetadata: normalized.context.auditMetadata });
        return { ok: true, toolId: "mcp.unregisterTool", output: output(normalized, { dryRun: false, providerCalled: true, result }), audit: [auditEvent("agentCore.basicTool.mcp.unregisterTool.executed", false, normalized.context, normalized.target.serverId, { toolName: normalized.target.toolName })], events: ["basicTool.mcp.unregisterTool.executed"] };
    }
    catch {
        return createMcpToolRegistryFailure("mcp.unregisterTool", "PROVIDER_REJECTED", "Runtime MCP provider failed unregisterTool.", "provider", normalized.context, normalized.target.serverId, "basicTool.mcp.unregisterTool.providerRejected");
    }
}
