/*
 * Copyright 2026, Jaime Terrats.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/**
 * Core logic for third-party MCP integration setup.
 *
 * Consumed by the CLI command (`sf setup-agents mcp`) and the VS Code extension.
 * Pure functions with no side-effects — callers handle I/O.
 */
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
import { homedir } from 'node:os';
import { join } from 'node:path';
import { MCP_INTEGRATIONS } from './mcp-registry.js';
/**
 * Returns integrations from the registry that are relevant for the given
 * profile IDs. An integration is relevant if at least one of its target
 * profiles is in the active set.
 */
export function getRelevantIntegrations(profileIds) {
    const ids = new Set(profileIds);
    return MCP_INTEGRATIONS.filter((integration) => [...integration.profiles].some((p) => ids.has(p)));
}
/**
 * Builds an mcp.json server entry from an integration definition and
 * user-provided credentials. For HTTP integrations the entry only needs
 * a `url`. For stdio integrations the entry includes command, args, and
 * env with credential values filled in.
 */
export function buildMcpEntry(integration, credentials) {
    const cfg = integration.config;
    if (cfg.transport === 'http') {
        const entry = { url: cfg.url, type: 'http' };
        if (cfg.requiresAuth && cfg.apiTokenEnvVar) {
            const token = credentials[cfg.apiTokenEnvVar] ?? process.env[cfg.apiTokenEnvVar] ?? '';
            if (token) {
                entry.headers = { Authorization: `Bearer ${token}` };
            }
        }
        return entry;
    }
    const env = {};
    for (const spec of integration.envVars) {
        env[spec.name] = credentials[spec.name] ?? '';
    }
    return {
        command: cfg.command,
        args: [...cfg.args],
        env,
        type: 'stdio',
    };
}
/**
 * Generates a human-readable setup guide for an integration.
 * Suitable for display in CLI output or webview.
 */
export function formatSetupGuide(integration) {
    const lines = [`## ${integration.label} Setup Guide\n`];
    for (const step of integration.setupGuide.steps) {
        lines.push(step);
        lines.push('');
    }
    lines.push(`Learn more: ${integration.setupGuide.learnMore}`);
    return lines.join('\n');
}
function readJson(path, fallback) {
    try {
        return JSON.parse(readFileSync(path, 'utf8'));
    }
    catch {
        return fallback;
    }
}
function writeJsonTarget(filePath, entries) {
    const dir = join(filePath, '..');
    if (!existsSync(dir))
        mkdirSync(dir, { recursive: true });
    const existing = readJson(filePath, { mcpServers: {} });
    if (!existing.mcpServers || typeof existing.mcpServers !== 'object')
        existing.mcpServers = {};
    Object.assign(existing.mcpServers, entries);
    writeFileSync(filePath, JSON.stringify(existing, null, 2) + '\n', 'utf8');
}
// ─── Extracted per-scope config builders (module-private) ────────────────────
function writeGlobalTargets(entries, home) {
    const written = [];
    // Cursor global
    const cursorGlobal = join(home, '.cursor', 'mcp.json');
    writeJsonTarget(cursorGlobal, entries);
    written.push(cursorGlobal);
    // Windsurf global
    const windsurfDir = join(home, '.codeium', 'windsurf');
    if (existsSync(windsurfDir)) {
        const windsurfGlobal = join(windsurfDir, 'mcp_config.json');
        writeJsonTarget(windsurfGlobal, entries);
        written.push(windsurfGlobal);
    }
    // Claude Desktop
    const claudeDesktopDir = join(home, 'Library', 'Application Support', 'Claude');
    if (existsSync(claudeDesktopDir)) {
        const claudeDesktopPath = join(claudeDesktopDir, 'claude_desktop_config.json');
        writeJsonTarget(claudeDesktopPath, entries);
        written.push(claudeDesktopPath);
    }
    // Claude Code global
    const claudeJsonPath = join(home, '.claude.json');
    if (existsSync(claudeJsonPath) || existsSync(join(home, '.claude'))) {
        const data = readJson(claudeJsonPath, {});
        if (!data.mcpServers)
            data.mcpServers = {};
        Object.assign(data.mcpServers, entries);
        writeFileSync(claudeJsonPath, JSON.stringify(data, null, 2) + '\n', 'utf8');
        written.push(claudeJsonPath);
    }
    return written;
}
function writeProjectTargets(entries, workspacePath, home) {
    const written = [];
    // Cursor project
    const cursorProject = join(workspacePath, '.cursor', 'mcp.json');
    writeJsonTarget(cursorProject, entries);
    written.push(cursorProject);
    // VS Code Copilot project
    if (existsSync(join(workspacePath, '.vscode'))) {
        const vscodePath = join(workspacePath, '.vscode', 'mcp.json');
        writeJsonTarget(vscodePath, entries);
        written.push(vscodePath);
    }
    // Windsurf project
    if (existsSync(join(workspacePath, '.windsurf'))) {
        const windsurfPath = join(workspacePath, '.windsurf', 'mcp.json');
        writeJsonTarget(windsurfPath, entries);
        written.push(windsurfPath);
    }
    // Claude Code project
    const claudeJsonPath = join(home, '.claude.json');
    if (existsSync(claudeJsonPath) ||
        existsSync(join(workspacePath, '.claude')) ||
        existsSync(join(workspacePath, 'CLAUDE.md'))) {
        const data = readJson(claudeJsonPath, {});
        if (!data.projects)
            data.projects = {};
        if (!data.projects[workspacePath])
            data.projects[workspacePath] = {};
        if (!data.projects[workspacePath].mcpServers)
            data.projects[workspacePath].mcpServers = {};
        Object.assign(data.projects[workspacePath].mcpServers, entries);
        writeFileSync(claudeJsonPath, JSON.stringify(data, null, 2) + '\n', 'utf8');
        written.push(claudeJsonPath);
    }
    return written;
}
// ─── Public write API ────────────────────────────────────────────────────────
/**
 * Writes third-party integration entries to every supported LLM config target:
 * Cursor, VS Code Copilot, Windsurf, Claude Desktop, and Claude Code (project + global).
 *
 * Mirrors the mcpConfigService.writeIntegrationConfig() logic from the VS Code extension
 * so the CLI produces the same propagation without importing extension code.
 */
export function writeIntegrationToAllTargets(entries, global, workspacePath) {
    const home = homedir();
    return global ? writeGlobalTargets(entries, home) : writeProjectTargets(entries, workspacePath, home);
}
//# sourceMappingURL=mcp-setup.js.map