import fs from 'fs';
import path from 'path';
import os from 'os';
import { getSettingsManager } from "../utils/settings-manager.js";
import { logger } from '../utils/logger.js';
/**
 * Resolve ${ENV_VAR} references in env values from process.env
 */
function resolveEnvVars(env) {
    if (!env)
        return env;
    const resolved = {};
    for (const [key, value] of Object.entries(env)) {
        const match = value.match(/^\$\{(\w+)\}$/);
        resolved[key] = match ? (process.env[match[1]] || '') : value;
    }
    return resolved;
}
/**
 * Resolve env vars in a server config's transport
 */
function resolveServerEnv(server) {
    if (server.transport?.env) {
        return { ...server, transport: { ...server.transport, env: resolveEnvVars(server.transport.env) } };
    }
    if (server.env) {
        return { ...server, env: resolveEnvVars(server.env) };
    }
    return server;
}
/**
 * Load MCP configuration from multiple sources (inspired by Claude Code)
 * Priority: Project .codebuddy/mcp.json > .codebuddy/settings.json > ~/.codebuddy/mcp.json
 */
export function loadMCPConfig() {
    const servers = [];
    const seenServers = new Set();
    // 1. First, try project-level .codebuddy/mcp.json (highest priority, committable)
    const projectMCPPath = path.join(process.cwd(), '.codebuddy', 'mcp.json');
    if (fs.existsSync(projectMCPPath)) {
        try {
            const projectMCP = JSON.parse(fs.readFileSync(projectMCPPath, 'utf-8'));
            const mcpServers = projectMCP.mcpServers || projectMCP.servers || {};
            for (const [name, config] of Object.entries(mcpServers)) {
                if (!seenServers.has(name)) {
                    const serverConfig = resolveServerEnv({ ...config, name });
                    // Skip disabled servers at load time
                    if (serverConfig.enabled === false) {
                        seenServers.add(name);
                        continue;
                    }
                    servers.push(serverConfig);
                    seenServers.add(name);
                }
            }
        }
        catch (error) {
            logger.warn('Failed to load project MCP config', { error });
        }
    }
    // 2. Then, try project settings (.codebuddy/settings.json)
    const manager = getSettingsManager();
    const projectSettings = manager.loadProjectSettings();
    if (projectSettings.mcpServers) {
        for (const [name, config] of Object.entries(projectSettings.mcpServers)) {
            if (!seenServers.has(name)) {
                servers.push(resolveServerEnv(config));
                seenServers.add(name);
            }
        }
    }
    // 3. Finally, try user-level ~/.codebuddy/mcp.json (lowest priority)
    const userMCPPath = path.join(os.homedir(), '.codebuddy', 'mcp.json');
    if (fs.existsSync(userMCPPath)) {
        try {
            const userMCP = JSON.parse(fs.readFileSync(userMCPPath, 'utf-8'));
            const mcpServers = userMCP.mcpServers || userMCP.servers || {};
            for (const [name, config] of Object.entries(mcpServers)) {
                if (!seenServers.has(name)) {
                    servers.push(resolveServerEnv({ ...config, name }));
                    seenServers.add(name);
                }
            }
        }
        catch (_error) {
            // Silently ignore user config errors
        }
    }
    return { servers };
}
export function saveMCPConfig(config) {
    const manager = getSettingsManager();
    const mcpServers = {};
    // Convert servers array to object keyed by name
    for (const server of config.servers) {
        mcpServers[server.name] = server;
    }
    manager.updateProjectSetting('mcpServers', mcpServers);
}
export function addMCPServer(config) {
    const manager = getSettingsManager();
    const projectSettings = manager.loadProjectSettings();
    const mcpServers = projectSettings.mcpServers || {};
    mcpServers[config.name] = config;
    manager.updateProjectSetting('mcpServers', mcpServers);
}
export function removeMCPServer(serverName) {
    const manager = getSettingsManager();
    const projectSettings = manager.loadProjectSettings();
    const mcpServers = projectSettings.mcpServers;
    if (mcpServers) {
        delete mcpServers[serverName];
        manager.updateProjectSetting('mcpServers', mcpServers);
    }
}
export function getMCPServer(serverName) {
    const manager = getSettingsManager();
    const projectSettings = manager.loadProjectSettings();
    return projectSettings.mcpServers?.[serverName];
}
// Predefined server configurations (disabled by default — user activates with API key)
export const PREDEFINED_SERVERS = {
    'brave-search': {
        name: 'brave-search',
        transport: {
            type: 'stdio',
            command: 'npx',
            args: ['-y', '@modelcontextprotocol/server-brave-search'],
            env: { BRAVE_API_KEY: process.env.BRAVE_API_KEY || '' },
        },
        enabled: false,
    },
    'playwright': {
        name: 'playwright',
        transport: {
            type: 'stdio',
            command: 'npx',
            args: ['-y', '@playwright/mcp@latest'],
        },
        enabled: false,
    },
    'exa-search': {
        name: 'exa-search',
        transport: {
            type: 'stdio',
            command: 'npx',
            args: ['-y', 'exa-mcp-server'],
            env: { EXA_API_KEY: process.env.EXA_API_KEY || '' },
        },
        enabled: false,
    },
};
/**
 * Save MCP configuration to project-level .codebuddy/mcp.json (committable)
 */
export function saveProjectMCPConfig(servers) {
    const projectMCPPath = path.join(process.cwd(), '.codebuddy', 'mcp.json');
    const projectDir = path.dirname(projectMCPPath);
    if (!fs.existsSync(projectDir)) {
        fs.mkdirSync(projectDir, { recursive: true });
    }
    const config = {
        mcpServers: servers
    };
    fs.writeFileSync(projectMCPPath, JSON.stringify(config, null, 2));
    return projectMCPPath;
}
/**
 * Create default MCP configuration template
 */
export function createMCPConfigTemplate() {
    const projectMCPPath = path.join(process.cwd(), '.codebuddy', 'mcp.json');
    const projectDir = path.dirname(projectMCPPath);
    if (!fs.existsSync(projectDir)) {
        fs.mkdirSync(projectDir, { recursive: true });
    }
    const template = {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "description": "MCP server configuration for this project. This file can be committed to share MCP servers with your team.",
        "mcpServers": {
            "example-stdio": {
                "name": "example-stdio",
                "type": "stdio",
                "command": "npx",
                "args": ["-y", "@example/mcp-server"],
                "env": {},
                "enabled": false
            },
            "example-http": {
                "name": "example-http",
                "type": "http",
                "url": "http://localhost:3000/mcp",
                "enabled": false
            },
            "brave-search": {
                "name": "brave-search",
                "type": "stdio",
                "command": "npx",
                "args": ["-y", "@modelcontextprotocol/server-brave-search"],
                "env": { "BRAVE_API_KEY": "" },
                "enabled": false
            },
            "playwright": {
                "name": "playwright",
                "type": "stdio",
                "command": "npx",
                "args": ["-y", "@playwright/mcp@latest"],
                "enabled": false
            },
            "exa-search": {
                "name": "exa-search",
                "type": "stdio",
                "command": "npx",
                "args": ["-y", "exa-mcp-server"],
                "env": { "EXA_API_KEY": "" },
                "enabled": false
            }
        }
    };
    fs.writeFileSync(projectMCPPath, JSON.stringify(template, null, 2));
    return projectMCPPath;
}
/**
 * Check if project has MCP configuration
 */
export function hasProjectMCPConfig() {
    const projectMCPPath = path.join(process.cwd(), '.codebuddy', 'mcp.json');
    return fs.existsSync(projectMCPPath);
}
/**
 * Get MCP configuration file paths
 */
export function getMCPConfigPaths() {
    return {
        project: path.join(process.cwd(), '.codebuddy', 'mcp.json'),
        user: path.join(os.homedir(), '.codebuddy', 'mcp.json')
    };
}
//# sourceMappingURL=config.js.map