"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.listMcpServers = listMcpServers;
exports.createMcpServer = createMcpServer;
exports.testConnection = testConnection;
exports.getMcpServer = getMcpServer;
exports.updateMcpServer = updateMcpServer;
exports.deleteMcpServer = deleteMcpServer;
exports.connectMcpServer = connectMcpServer;
exports.disconnectMcpServer = disconnectMcpServer;
exports.getCredentialStatus = getCredentialStatus;
const mcpDbService = __importStar(require("../../services/mcp/db"));
const mcp_1 = require("../../services/mcp");
/**
 * List registered MCP servers with optional filtering and pagination.
 *
 * @param input.status — filter by server status (e.g. 'active', 'inactive')
 * @param input.auto_connect — filter by auto-connect setting
 * @param input.search — free-text search across server names and descriptions
 * @param input.tags — filter to servers matching any of these tags
 * @param input.limit — maximum number of results to return
 * @param input.offset — pagination offset
 * @returns `{ status: 200, data: { ... } }` paginated list of MCP server records
 */
async function listMcpServers(input) {
    try {
        const result = await mcpDbService.listMcpServers(input);
        return { status: 200, data: result };
    }
    catch (err) {
        return { status: 500, error: err.message };
    }
}
/**
 * Register a new MCP server.
 *
 * Returns 409 if a server with the same name already exists.
 *
 * @param input.name — unique display name for the server (required)
 * @param input.description — optional human-readable description
 * @param input.transport_type — transport protocol, e.g. 'sse', 'stdio' (required)
 * @param input.transport_config — transport-specific connection settings (required)
 * @param input.auto_connect — whether to connect automatically on startup
 * @param input.metadata — arbitrary key-value metadata
 * @param input.tags — tags for categorization and filtering
 * @param input.compile_hints — optional hints used during tool compilation
 * @param input.credential_providers — OAuth/credential provider identifiers required by this server
 * @returns `{ status: 201, data: { ... } }` the created MCP server record
 */
async function createMcpServer(input) {
    try {
        if (!input.name || !input.transport_type || !input.transport_config) {
            return { status: 400, error: 'name, transport_type, and transport_config are required' };
        }
        const server = await mcpDbService.createMcpServer(input);
        return { status: 201, data: server };
    }
    catch (err) {
        if (err.message?.includes('duplicate key') || err.code === '23505') {
            return { status: 409, error: 'MCP server with that name already exists' };
        }
        return { status: 500, error: err.message };
    }
}
/**
 * Test connectivity to an MCP server without persisting it.
 *
 * Attempts to establish a connection using the provided transport
 * configuration and returns the result. On failure, returns a
 * successful (200) response with `success: false` and the error message.
 *
 * @param input.transport_type — transport protocol to test (required)
 * @param input.transport_config — transport-specific connection settings (required)
 * @returns `{ status: 200, data: { success, error?, tools } }` connection test result
 */
async function testConnection(input) {
    try {
        if (!input.transport_type || !input.transport_config) {
            return { status: 400, error: 'transport_type and transport_config are required' };
        }
        const { testConnection: testConn } = await Promise.resolve().then(() => __importStar(require('../../services/mcp/client/connection')));
        const result = await testConn(input.transport_type, input.transport_config);
        return { status: 200, data: result };
    }
    catch (err) {
        return { status: 200, data: { success: false, error: err.message, tools: [] } };
    }
}
/**
 * Retrieve a single MCP server by ID.
 *
 * @param input.id — the MCP server identifier
 * @returns `{ status: 200, data: { ... } }` the MCP server record, or 404 if not found
 */
async function getMcpServer(input) {
    try {
        const server = await mcpDbService.getMcpServer(input.id);
        if (!server) {
            return { status: 404, error: 'MCP server not found' };
        }
        return { status: 200, data: server };
    }
    catch (err) {
        return { status: 500, error: err.message };
    }
}
/**
 * Update fields on an existing MCP server.
 *
 * Accepts any subset of mutable server fields alongside the required ID.
 *
 * @param input.id — the MCP server identifier (required)
 * @param input.[key] — any mutable server field to update (name, description, transport_config, etc.)
 * @returns `{ status: 200, data: { ... } }` the updated server record, or 404 if not found
 */
async function updateMcpServer(input) {
    try {
        const { id, ...fields } = input;
        const server = await mcpDbService.updateMcpServer(id, fields);
        if (!server) {
            return { status: 404, error: 'MCP server not found' };
        }
        return { status: 200, data: server };
    }
    catch (err) {
        return { status: 500, error: err.message };
    }
}
/**
 * Delete an MCP server by ID.
 *
 * @param input.id — the MCP server identifier
 * @returns `{ status: 200, data: { deleted: true } }` on success, or 404 if not found
 */
async function deleteMcpServer(input) {
    try {
        const deleted = await mcpDbService.deleteMcpServer(input.id);
        if (!deleted) {
            return { status: 404, error: 'MCP server not found' };
        }
        return { status: 200, data: { deleted: true } };
    }
    catch (err) {
        return { status: 500, error: err.message };
    }
}
/**
 * Establish a live connection to a registered MCP server.
 *
 * Requires the MCP adapter to be registered in the registry.
 *
 * @param input.id — the MCP server identifier to connect
 * @returns `{ status: 200, data: { connected, serverId } }` confirmation of the connection
 */
async function connectMcpServer(input) {
    try {
        const adapter = mcp_1.mcpRegistry.current;
        if (!adapter) {
            return { status: 400, error: 'MCP adapter not registered' };
        }
        await adapter.connectClient(input.id);
        return { status: 200, data: { connected: true, serverId: input.id } };
    }
    catch (err) {
        return { status: 500, error: err.message };
    }
}
/**
 * Disconnect a live MCP server connection.
 *
 * Requires the MCP adapter to be registered in the registry.
 *
 * @param input.id — the MCP server identifier to disconnect
 * @returns `{ status: 200, data: { disconnected, serverId } }` confirmation of the disconnection
 */
async function disconnectMcpServer(input) {
    try {
        const adapter = mcp_1.mcpRegistry.current;
        if (!adapter) {
            return { status: 400, error: 'MCP adapter not registered' };
        }
        await adapter.disconnectClient(input.id);
        return { status: 200, data: { disconnected: true, serverId: input.id } };
    }
    catch (err) {
        return { status: 500, error: err.message };
    }
}
/**
 * Check which credential providers are registered vs missing for an MCP server.
 *
 * Resolves each credential provider required by the server against the
 * authenticated user's stored credentials.
 *
 * @param input.id — the MCP server identifier
 * @param auth — authenticated user context used to resolve credentials
 * @returns `{ status: 200, data: { required, registered, missing } }` credential status arrays
 */
async function getCredentialStatus(input, auth) {
    try {
        const server = await mcpDbService.getMcpServer(input.id);
        if (!server) {
            return { status: 404, error: 'MCP server not found' };
        }
        const required = server.credential_providers ?? [];
        const registered = [];
        const missing = [];
        if (auth?.userId && required.length > 0) {
            const { resolveCredential } = await Promise.resolve().then(() => __importStar(require('../../services/iam/credentials')));
            for (const provider of required) {
                const cred = await resolveCredential({ id: auth.userId, type: 'user', roles: [] }, provider);
                if (cred)
                    registered.push(provider);
                else
                    missing.push(provider);
            }
        }
        else {
            missing.push(...required);
        }
        return { status: 200, data: { required, registered, missing } };
    }
    catch (err) {
        return { status: 500, error: err.message };
    }
}
