import { McpHttpClient } from "./httpClient.js";
import { McpStdioClient } from "./stdioClient.js";
export class McpSessionPool {
    projectPath;
    sessions = new Map();
    constructor(projectPath) {
        this.projectPath = projectPath;
    }
    has(name) {
        return this.sessions.has(name);
    }
    async connect(server, options) {
        const existing = this.sessions.get(server.name);
        if (existing) {
            existing.lastUsedAtMs = Date.now();
            return {
                server: existing.server,
                tools: existing.tools,
                stderr: stderrOf(existing.client),
            };
        }
        const client = createClient(this.projectPath, server, options);
        const serverInfo = await client.connect();
        const tools = await client.listTools();
        const now = Date.now();
        this.sessions.set(server.name, {
            name: server.name,
            type: server.type,
            client,
            server: serverInfo,
            tools,
            connectedAtMs: now,
            lastUsedAtMs: now,
        });
        return {
            server: serverInfo,
            tools,
            stderr: stderrOf(client),
        };
    }
    async probe(name) {
        const session = this.requireSession(name);
        session.tools = await session.client.listTools();
        session.lastUsedAtMs = Date.now();
        return {
            server: session.server,
            tools: session.tools,
            stderr: stderrOf(session.client),
        };
    }
    async callTool(name, toolName, args) {
        const session = this.requireSession(name);
        const result = await session.client.callTool(toolName, args);
        session.lastUsedAtMs = Date.now();
        return {
            result,
            stderr: stderrOf(session.client),
        };
    }
    close(name) {
        if (name) {
            const session = this.sessions.get(name);
            if (!session)
                return 0;
            session.client.close();
            this.sessions.delete(name);
            return 1;
        }
        const count = this.sessions.size;
        for (const session of this.sessions.values())
            session.client.close();
        this.sessions.clear();
        return count;
    }
    list() {
        return [...this.sessions.values()]
            .map((session) => ({
            name: session.name,
            type: session.type,
            toolCount: session.tools.length,
            connectedAtMs: session.connectedAtMs,
            lastUsedAtMs: session.lastUsedAtMs,
        }))
            .sort((a, b) => a.name.localeCompare(b.name));
    }
    requireSession(name) {
        const session = this.sessions.get(name);
        if (!session)
            throw new Error(`MCP server is not connected: ${name}`);
        return session;
    }
}
function createClient(projectPath, server, options) {
    if (server.type === "stdio") {
        if (!options.allowShell)
            throw new Error("MCP stdio connection requires shell permission. Run /shell on first.");
        return new McpStdioClient(serverCommand(server), projectPath, options.timeoutMs ?? 10_000);
    }
    if (server.type === "http") {
        if (!server.url)
            throw new Error(`MCP server has no url: ${server.name}`);
        return new McpHttpClient(server.url, options.timeoutMs ?? 10_000);
    }
    throw new Error(`MCP connection pool currently supports stdio and http servers only: ${server.name}`);
}
function serverCommand(server) {
    return [server.command, ...(server.args ?? [])].filter(Boolean).join(" ");
}
function stderrOf(client) {
    return client instanceof McpStdioClient ? client.stderr() : "";
}
