"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.ClaudeCodeMCPClient = exports.ClaudeCodeMCPConfig = void 0;
const MCPClient_1 = require("../MCPClient");
const defaults_1 = require("../defaults");
// On Windows, Claude Code ships as `claude.cmd` when installed via npm.
// The stock `child_process.spawnSync` does not consult PATHEXT, so we
// route through the cross-platform wrapper which handles the shim.
const cross_platform_spawn_js_1 = require("../../../utils/cross-platform-spawn.js");
const analytics_1 = require("../../../utils/analytics");
const debug_1 = require("../../../utils/debug");
const os = __importStar(require("os"));
const path = __importStar(require("path"));
const fs = __importStar(require("fs"));
exports.ClaudeCodeMCPConfig = defaults_1.DefaultMCPClientConfig;
class ClaudeCodeMCPClient extends MCPClient_1.DefaultMCPClient {
    name = 'Claude Code';
    claudeBinaryPath = null;
    constructor() {
        super();
    }
    findClaudeBinary() {
        if (this.claudeBinaryPath) {
            return this.claudeBinaryPath;
        }
        // Common installation paths for Claude Code CLI
        const possiblePaths = [
            path.join(os.homedir(), '.local', 'bin', 'claude'),
            path.join(os.homedir(), '.claude', 'local', 'claude'),
            '/usr/local/bin/claude',
            '/opt/homebrew/bin/claude',
        ];
        for (const claudePath of possiblePaths) {
            if (fs.existsSync(claudePath)) {
                (0, debug_1.debug)(`  Found claude binary at: ${claudePath}`);
                this.claudeBinaryPath = claudePath;
                return claudePath;
            }
        }
        // Search PATH directories manually — no exec, no tainted strings passed
        // to child_process.
        const pathDirs = (process.env.PATH ?? '').split(path.delimiter);
        for (const dir of pathDirs) {
            if (!dir)
                continue;
            const candidate = path.join(dir, 'claude');
            if (fs.existsSync(candidate)) {
                (0, debug_1.debug)(`  Found claude in PATH: ${candidate}`);
                this.claudeBinaryPath = candidate;
                return candidate;
            }
        }
        return null;
    }
    isClientSupported() {
        try {
            (0, debug_1.debug)('  Checking for Claude Code...');
            const claudeBinary = this.findClaudeBinary();
            if (!claudeBinary) {
                (0, debug_1.debug)('  Claude Code not found. Installation paths checked:');
                (0, debug_1.debug)(`    - ${path.join(os.homedir(), '.local', 'bin', 'claude')}`);
                (0, debug_1.debug)(`    - ${path.join(os.homedir(), '.claude', 'local', 'claude')}`);
                (0, debug_1.debug)(`    - /usr/local/bin/claude`);
                (0, debug_1.debug)(`    - /opt/homebrew/bin/claude`);
                (0, debug_1.debug)(`    - PATH`);
                return Promise.resolve(false);
            }
            const result = (0, cross_platform_spawn_js_1.spawnSync)(claudeBinary, ['--version'], { stdio: 'pipe' });
            if (result.status !== 0) {
                return Promise.resolve(false);
            }
            const version = result.stdout.toString().trim();
            (0, debug_1.debug)(`  Claude Code detected: ${version}`);
            return Promise.resolve(true);
        }
        catch (error) {
            (0, debug_1.debug)(`  Claude Code check failed: ${error instanceof Error ? error.message : String(error)}`);
            return Promise.resolve(false);
        }
    }
    isServerInstalled(local) {
        try {
            const claudeBinary = this.findClaudeBinary();
            if (!claudeBinary) {
                return Promise.resolve(false);
            }
            const result = (0, cross_platform_spawn_js_1.spawnSync)(claudeBinary, ['mcp', 'list'], {
                stdio: 'pipe',
            });
            const serverName = local ? 'amplitude-local' : 'amplitude';
            if (result.stdout.toString().includes(serverName)) {
                return Promise.resolve(true);
            }
        }
        catch {
            //
        }
        return Promise.resolve(false);
    }
    getConfigPath() {
        throw new Error('Not implemented');
    }
    addServer(apiKey, selectedFeatures, local, zone = 'us') {
        const binary = this.findClaudeBinary();
        if (!binary) {
            return Promise.resolve({ success: false });
        }
        const serverName = local ? 'amplitude-local' : 'amplitude';
        const url = (0, defaults_1.buildMCPUrl)('streamable-http', selectedFeatures, local, zone);
        // Build args array — no shell interpolation, no injection risk
        const addArgs = ['mcp', 'add', '--transport', 'http', serverName, url];
        if (apiKey) {
            addArgs.push('--header', `Authorization: Bearer ${apiKey}`);
        }
        addArgs.push('-s', 'user');
        let addResult = (0, cross_platform_spawn_js_1.spawnSync)(binary, addArgs, { stdio: 'pipe' });
        if (addResult.status !== 0) {
            const stderr = addResult.stderr?.toString() ?? '';
            // If the server already exists, remove and re-add so the config stays
            // current (e.g. URL params or auth changes).
            if (stderr.includes('already exists')) {
                const removeResult = (0, cross_platform_spawn_js_1.spawnSync)(binary, ['mcp', 'remove', '--scope', 'user', serverName], { stdio: 'pipe' });
                if (removeResult.status !== 0) {
                    analytics_1.analytics.captureException(new Error(`Failed to remove existing Claude Code MCP entry: ${removeResult.stderr?.toString()}`));
                    return Promise.resolve({ success: false });
                }
                addResult = (0, cross_platform_spawn_js_1.spawnSync)(binary, addArgs, { stdio: 'pipe' });
            }
            if (addResult.status !== 0) {
                analytics_1.analytics.captureException(new Error(`Failed to add server to Claude Code: ${addResult.stderr?.toString()}`));
                return Promise.resolve({ success: false });
            }
        }
        return Promise.resolve({ success: true });
    }
    removeServer(local) {
        const binary = this.findClaudeBinary();
        if (!binary) {
            return Promise.resolve({ success: false });
        }
        const serverName = local ? 'amplitude-local' : 'amplitude';
        const result = (0, cross_platform_spawn_js_1.spawnSync)(binary, ['mcp', 'remove', '--scope', 'user', serverName], { stdio: 'pipe' });
        if (result.status !== 0) {
            analytics_1.analytics.captureException(new Error(`Failed to remove server from Claude Code: ${result.stderr?.toString()}`));
            return Promise.resolve({ success: false });
        }
        return Promise.resolve({ success: true });
    }
}
exports.ClaudeCodeMCPClient = ClaudeCodeMCPClient;
