import { getMcpDiscoverySummary, } from "./config.js";
import { updateMetadataCache, updateStatusBar, getFailureAgeSeconds } from "./init.js";
import { buildToolMetadata } from "./tool-metadata.js";
import { supportsOAuth, authenticate } from "./mcp-auth-flow.js";
import { loadOnboardingState, markSharedConfigHintShown } from "./onboarding-state.js";
export async function showStatus(state, ctx) {
    if (!ctx.hasUI)
        return;
    const lines = ["MCP Server Status:", ""];
    for (const name of Object.keys(state.config.mcpServers)) {
        const connection = state.manager.getConnection(name);
        const metadata = state.toolMetadata.get(name);
        const toolCount = metadata?.length ?? 0;
        const failedAgo = getFailureAgeSeconds(state, name);
        let status = "not connected";
        let statusIcon = "○";
        let failed = false;
        if (connection?.status === "connected") {
            status = "connected";
            statusIcon = "✓";
        }
        else if (connection?.status === "needs-auth") {
            status = "needs auth";
            statusIcon = "⚠";
        }
        else if (failedAgo !== null) {
            status = `failed ${failedAgo}s ago`;
            statusIcon = "✗";
            failed = true;
        }
        else if (metadata !== undefined) {
            status = "cached";
        }
        const toolSuffix = failed ? "" : ` (${toolCount} tools${status === "cached" ? ", cached" : ""})`;
        lines.push(`${statusIcon} ${name}: ${status}${toolSuffix}`);
    }
    if (Object.keys(state.config.mcpServers).length === 0) {
        lines.push("No MCP servers configured");
        lines.push("Run /mcp setup to adopt imports or scaffold a starter .mcp.json");
    }
    ctx.ui.notify(lines.join("\n"), "info");
}
export async function showTools(state, ctx) {
    if (!ctx.hasUI)
        return;
    const allTools = [...state.toolMetadata.values()].flat().map(m => m.name);
    if (allTools.length === 0) {
        ctx.ui.notify("No MCP tools available", "info");
        return;
    }
    const lines = [
        "MCP Tools:",
        "",
        ...allTools.map(t => `  ${t}`),
        "",
        `Total: ${allTools.length} tools`,
    ];
    ctx.ui.notify(lines.join("\n"), "info");
}
export async function reconnectServers(state, ctx, targetServer) {
    if (targetServer && !state.config.mcpServers[targetServer]) {
        if (ctx.hasUI) {
            ctx.ui.notify(`Server "${targetServer}" not found in config`, "error");
        }
        return;
    }
    const entries = targetServer
        ? [[targetServer, state.config.mcpServers[targetServer]]]
        : Object.entries(state.config.mcpServers);
    for (const [name, definition] of entries) {
        try {
            await state.manager.close(name);
            const connection = await state.manager.connect(name, definition);
            if (connection.status === "needs-auth") {
                if (ctx.hasUI) {
                    ctx.ui.notify(`MCP: ${name} requires OAuth. Run /mcp-auth ${name} first.`, "warning");
                }
                continue;
            }
            const prefix = state.config.settings?.toolPrefix ?? "server";
            const { metadata, failedTools } = buildToolMetadata(connection.tools, connection.resources, definition, name, prefix);
            state.toolMetadata.set(name, metadata);
            updateMetadataCache(state, name);
            state.failureTracker.delete(name);
            if (ctx.hasUI) {
                ctx.ui.notify(`MCP: Reconnected to ${name} (${connection.tools.length} tools, ${connection.resources.length} resources)`, "info");
                if (failedTools.length > 0) {
                    ctx.ui.notify(`MCP: ${name} - ${failedTools.length} tools skipped`, "warning");
                }
            }
        }
        catch (error) {
            const message = error instanceof Error ? error.message : String(error);
            state.failureTracker.set(name, Date.now());
            if (ctx.hasUI) {
                ctx.ui.notify(`MCP: Failed to reconnect to ${name}: ${message}`, "error");
            }
        }
    }
    updateStatusBar(state);
}
export async function authenticateServer(serverName, config, ctx) {
    if (!ctx.hasUI)
        return;
    const definition = config.mcpServers[serverName];
    if (!definition) {
        ctx.ui.notify(`Server "${serverName}" not found in config`, "error");
        return;
    }
    if (!supportsOAuth(definition)) {
        ctx.ui.notify(`Server "${serverName}" does not use OAuth authentication.\n` +
            `Set "auth": "oauth" or omit auth for auto-detection.`, "error");
        return;
    }
    if (!definition.url) {
        ctx.ui.notify(`Server "${serverName}" has no URL configured (OAuth requires HTTP transport)`, "error");
        return;
    }
    try {
        const status = await authenticate(serverName, definition.url, definition);
        if (status === "authenticated") {
            ctx.ui.notify(`OAuth authentication successful for "${serverName}"!\n` +
                `Run /mcp reconnect ${serverName} to connect with the new token.`, "info");
        }
        else {
            ctx.ui.notify(`OAuth authentication failed for "${serverName}".`, "error");
        }
    }
    catch (error) {
        const message = error instanceof Error ? error.message : String(error);
        ctx.ui.notify(`Failed to authenticate "${serverName}": ${message}`, "error");
    }
}
export async function showSetupStatus(state, ext, ctx, configOverridePath) {
    // Show MCP status first, then check for shared-config discovery hints
    await showStatus(state, ctx);
    if (!ctx.hasUI)
        return;
    const discovery = getMcpDiscoverySummary(configOverridePath);
    const onboardingState = loadOnboardingState();
    if (discovery.hasSharedServers && !onboardingState.sharedConfigHintShown) {
        const sharedSources = discovery.sources.filter((source) => source.kind === "shared" && source.serverCount > 0);
        const sourceList = sharedSources.map((source) => source.path).join(", ");
        ctx.ui.notify(`Using standard MCP config from ${sourceList}.\n` +
            "Pi only writes compatibility imports and adapter-specific overrides into Pi-owned files when needed.", "info");
        if (discovery.fingerprint) {
            markSharedConfigHintShown(discovery.fingerprint);
        }
    }
}
