"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 (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.showClaudeNotFoundError = exports.getClaudeAuthStatus = exports.isClaudeCliVersionAtLeast = exports.compareClaudeCliVersions = exports.getClaudeCliVersion = exports.getClaudeCliInfo = exports.detectClaudeCli = void 0;
const fs = __importStar(require("fs"));
const child_process_1 = require("child_process");
const helpers_1 = require("./helpers");
const shell_executor_1 = require("./shell-executor");
/**
 * Windows installation paths for Claude CLI
 * Checked as fallback when 'where.exe claude' fails
 *
 * Priority order:
 * 1. Native installer path (irm https://claude.ai/install.ps1 | iex)
 * 2. npm/bun global install locations
 */
const WINDOWS_NATIVE_PATHS = [
    // Native installer location (confirmed from Claude's install.ps1)
    // Source: https://github.com/anthropics/claude-code/issues/18183
    '%USERPROFILE%\\.local\\bin\\claude.exe',
    // npm/bun global install locations (already in PATH, but check as fallback)
    '%APPDATA%\\npm\\claude.cmd',
    '%USERPROFILE%\\.bun\\bin\\claude.exe',
];
/**
 * Check common Windows installation paths for Claude CLI
 * Returns the first valid path found, or null
 *
 * Note: Uses expandPath() from helpers which handles %VAR% expansion on Windows.
 * This function is only called when isWindows is true (see detectClaudeCli).
 */
function findClaudeInWindowsPaths() {
    for (const template of WINDOWS_NATIVE_PATHS) {
        const expanded = (0, helpers_1.expandPath)(template);
        if (fs.existsSync(expanded)) {
            return expanded;
        }
    }
    return null;
}
/**
 * Detect Claude CLI executable
 */
function detectClaudeCli() {
    // Priority 1: CCS_CLAUDE_PATH environment variable (if user wants custom path)
    if (process.env.CCS_CLAUDE_PATH) {
        const ccsPath = (0, helpers_1.expandPath)(process.env.CCS_CLAUDE_PATH);
        // Basic validation: file exists
        if (fs.existsSync(ccsPath)) {
            return ccsPath;
        }
        // Invalid CCS_CLAUDE_PATH - show warning and fall back to PATH
        console.warn('[!] Warning: CCS_CLAUDE_PATH is set but file not found:', ccsPath);
        console.warn('    Falling back to system PATH lookup...');
    }
    // Priority 2: Resolve 'claude' from PATH using which/where.exe
    // This fixes Windows npm installation where spawn() can't resolve bare command names
    // SECURITY: Commands are hardcoded literals with no user input - safe from injection
    const isWindows = process.platform === 'win32';
    try {
        const cmd = isWindows ? 'where.exe claude' : 'which claude';
        const result = (0, child_process_1.execSync)(cmd, {
            encoding: 'utf8',
            stdio: ['ignore', 'pipe', 'ignore'],
            timeout: 5000, // 5 second timeout to prevent hangs
        }).trim();
        // where.exe may return multiple lines (all matches in PATH order)
        const matches = result
            .split('\n')
            .map((p) => p.trim())
            .filter((p) => p);
        if (isWindows) {
            // On Windows, prefer executables with extensions (.exe, .cmd, .bat)
            // where.exe often returns file without extension first, then the actual .cmd wrapper
            const withExtension = matches.find((p) => /\.(exe|cmd|bat|ps1)$/i.test(p));
            const claudePath = withExtension || matches[0];
            if (claudePath && fs.existsSync(claudePath)) {
                return claudePath;
            }
        }
        else {
            // On Unix, first match is fine
            const claudePath = matches[0];
            if (claudePath && fs.existsSync(claudePath)) {
                return claudePath;
            }
        }
    }
    catch (_err) {
        // Command failed - claude not in PATH
        // Fall through to Windows fallback or return null
    }
    // Priority 3 (Windows only): Check common native installer locations
    // This helps users who installed via Windows MSI/EXE but haven't run 'claude install'
    if (isWindows) {
        const nativePath = findClaudeInWindowsPaths();
        if (nativePath) {
            return nativePath;
        }
    }
    // Priority 4: Claude not found
    return null;
}
exports.detectClaudeCli = detectClaudeCli;
/**
 * Get detailed Claude CLI information
 */
function getClaudeCliInfo() {
    const claudePath = detectClaudeCli();
    if (!claudePath) {
        return null;
    }
    const isWindows = process.platform === 'win32';
    const needsShell = isWindows && /\.(cmd|bat|ps1)$/i.test(claudePath);
    return {
        path: claudePath,
        isWindows,
        needsShell,
    };
}
exports.getClaudeCliInfo = getClaudeCliInfo;
function runClaudeCliCommand(args, envOverrides) {
    const cliInfo = getClaudeCliInfo();
    if (!cliInfo) {
        return null;
    }
    const env = (0, shell_executor_1.stripClaudeCodeEnv)((0, shell_executor_1.stripAnthropicEnv)({ ...process.env, ...envOverrides }));
    const { path: claudePath, needsShell } = cliInfo;
    const isWindows = process.platform === 'win32';
    const isPowerShellScript = isWindows && /\.ps1$/i.test(claudePath);
    try {
        if (isPowerShellScript) {
            return (0, child_process_1.execFileSync)('powershell.exe', ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', claudePath, ...args], {
                encoding: 'utf8',
                stdio: ['ignore', 'pipe', 'pipe'],
                timeout: 5000,
                env,
            }).trim();
        }
        if (needsShell) {
            const shell = (0, shell_executor_1.getWindowsEscapedCommandShell)();
            return (0, child_process_1.execSync)([claudePath, ...args].map(shell_executor_1.escapeShellArg).join(' '), {
                encoding: 'utf8',
                stdio: ['ignore', 'pipe', 'pipe'],
                timeout: 5000,
                shell: typeof shell === 'string' ? shell : undefined,
                env,
            }).trim();
        }
        return (0, child_process_1.execFileSync)(claudePath, args, {
            encoding: 'utf8',
            stdio: ['ignore', 'pipe', 'pipe'],
            timeout: 5000,
            env,
        }).trim();
    }
    catch (error) {
        if (typeof error === 'object' && error !== null && 'stdout' in error) {
            const stdout = error.stdout;
            if (typeof stdout === 'string') {
                const trimmed = stdout.trim();
                return trimmed.length > 0 ? trimmed : null;
            }
            if (Buffer.isBuffer(stdout)) {
                const trimmed = stdout.toString('utf8').trim();
                return trimmed.length > 0 ? trimmed : null;
            }
        }
        return null;
    }
}
function getClaudeCliVersion() {
    const output = runClaudeCliCommand(['--version']);
    const versionMatch = output?.match(/(\d+\.\d+\.\d+)/);
    return versionMatch ? versionMatch[1] : null;
}
exports.getClaudeCliVersion = getClaudeCliVersion;
function compareClaudeCliVersions(left, right) {
    const leftParts = left.split('.').map((value) => Number.parseInt(value, 10) || 0);
    const rightParts = right.split('.').map((value) => Number.parseInt(value, 10) || 0);
    const maxLength = Math.max(leftParts.length, rightParts.length);
    for (let index = 0; index < maxLength; index += 1) {
        const leftValue = leftParts[index] ?? 0;
        const rightValue = rightParts[index] ?? 0;
        if (leftValue !== rightValue) {
            return leftValue > rightValue ? 1 : -1;
        }
    }
    return 0;
}
exports.compareClaudeCliVersions = compareClaudeCliVersions;
function isClaudeCliVersionAtLeast(currentVersion, minimumVersion) {
    return currentVersion !== null && compareClaudeCliVersions(currentVersion, minimumVersion) >= 0;
}
exports.isClaudeCliVersionAtLeast = isClaudeCliVersionAtLeast;
function getClaudeAuthStatus(envOverrides) {
    const output = runClaudeCliCommand(['auth', 'status'], envOverrides);
    if (!output) {
        return null;
    }
    try {
        const parsed = JSON.parse(output);
        if (typeof parsed.loggedIn !== 'boolean') {
            return null;
        }
        return {
            loggedIn: parsed.loggedIn,
            authMethod: parsed.authMethod ?? null,
            apiProvider: parsed.apiProvider ?? null,
            email: parsed.email ?? null,
            orgId: parsed.orgId ?? null,
            orgName: parsed.orgName ?? null,
            subscriptionType: parsed.subscriptionType ?? null,
        };
    }
    catch {
        return null;
    }
}
exports.getClaudeAuthStatus = getClaudeAuthStatus;
/**
 * Show Claude not found error
 */
function showClaudeNotFoundError() {
    console.error('ERROR: Claude CLI not found in PATH');
    console.error('Install from: https://docs.claude.com/en/docs/claude-code/installation');
    process.exit(1);
}
exports.showClaudeNotFoundError = showClaudeNotFoundError;
//# sourceMappingURL=claude-detector.js.map