"use strict";
/**
 * Package Manager Detector Utilities
 *
 * Detect the package manager and install root that own the CURRENT CCS binary.
 * This is intentionally different from "which package manager has CCS installed
 * somewhere on the machine" because self-update must target the current install.
 */
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.formatManualUpdateCommand = exports.readInstalledPackageState = exports.readInstalledPackageVersion = exports.buildPackageManagerEnv = exports.detectPackageManager = exports.detectCurrentInstall = void 0;
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const CCS_PACKAGE_NAME = '@kaitranntt/ccs';
function resolveScriptPath(scriptPath) {
    // Keep Windows-style absolute test fixtures stable on non-Windows hosts, but
    // still resolve real POSIX symlink paths such as ~/.bun/bin/ccs.
    if (path.win32.isAbsolute(scriptPath) && !path.isAbsolute(scriptPath)) {
        return scriptPath;
    }
    try {
        return fs.realpathSync(scriptPath);
    }
    catch {
        return path.resolve(scriptPath);
    }
}
function findPackageRoot(scriptPath) {
    let currentDir = path.dirname(scriptPath);
    for (let i = 0; i < 8; i++) {
        const packageJsonPath = path.join(currentDir, 'package.json');
        if (fs.existsSync(packageJsonPath)) {
            try {
                const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
                if (packageJson.name === CCS_PACKAGE_NAME) {
                    return currentDir;
                }
            }
            catch {
                // Ignore malformed package.json and keep walking upward.
            }
        }
        const parentDir = path.dirname(currentDir);
        if (parentDir === currentDir) {
            break;
        }
        currentDir = parentDir;
    }
    return null;
}
function getPrefixBeforeMarker(packageRoot, marker) {
    const index = packageRoot.lastIndexOf(marker);
    return index >= 0 ? packageRoot.slice(0, index) || path.parse(packageRoot).root : null;
}
function inferInstallFromPath(targetPath) {
    const normalizedPath = targetPath.split(path.sep).join('/');
    if (normalizedPath.includes(`/install/global/node_modules/@kaitranntt/ccs`) ||
        normalizedPath.includes(`/.bun/install/global/node_modules/@kaitranntt/ccs`)) {
        return {
            manager: 'bun',
            prefix: getPrefixBeforeMarker(targetPath, `${path.sep}install${path.sep}global${path.sep}node_modules`),
        };
    }
    if (normalizedPath.includes(`/global/node_modules/@kaitranntt/ccs`)) {
        return {
            manager: 'yarn',
            prefix: getPrefixBeforeMarker(targetPath, `${path.sep}global${path.sep}node_modules`),
        };
    }
    if (normalizedPath.includes('/global/') &&
        normalizedPath.includes('/.pnpm/') &&
        normalizedPath.includes('/node_modules/@kaitranntt/ccs')) {
        const pnpmVirtualStoreMatch = targetPath.match(new RegExp(`${path.sep.replace(/\\/g, '\\\\')}global${path.sep.replace(/\\/g, '\\\\')}[^${path.sep.replace(/\\/g, '\\\\')}]+${path.sep.replace(/\\/g, '\\\\')}\\.pnpm${path.sep.replace(/\\/g, '\\\\')}`));
        if (pnpmVirtualStoreMatch) {
            return {
                manager: 'pnpm',
                prefix: getPrefixBeforeMarker(targetPath, `${path.sep}global${path.sep}`),
            };
        }
    }
    if (normalizedPath.includes('/global/') &&
        normalizedPath.includes('/node_modules/@kaitranntt/ccs')) {
        const pnpmFlatMatch = normalizedPath.match(/\/global\/([^/]+)\/node_modules\/@kaitranntt\/ccs/);
        if (!pnpmFlatMatch || pnpmFlatMatch[1] === 'lib') {
            return null;
        }
        return {
            manager: 'pnpm',
            prefix: getPrefixBeforeMarker(targetPath, `${path.sep}global${path.sep}`),
        };
    }
    if (normalizedPath.includes('/.pnpm/') &&
        normalizedPath.includes('/node_modules/@kaitranntt/ccs')) {
        return {
            manager: 'pnpm',
            prefix: null,
        };
    }
    if (normalizedPath.includes('/lib/node_modules/@kaitranntt/ccs')) {
        return {
            manager: 'npm',
            prefix: getPrefixBeforeMarker(targetPath, `${path.sep}lib${path.sep}node_modules`),
        };
    }
    if (normalizedPath.includes('/node_modules/@kaitranntt/ccs') &&
        !normalizedPath.includes('/global/node_modules/@kaitranntt/ccs') &&
        !normalizedPath.includes('/install/global/node_modules/@kaitranntt/ccs') &&
        !normalizedPath.includes('/.pnpm/')) {
        return {
            manager: 'npm',
            prefix: getPrefixBeforeMarker(targetPath, `${path.sep}node_modules`),
        };
    }
    return null;
}
/**
 * Detect the current install owner from the path of the running script.
 * Defaults to npm when the path is ambiguous because npm's global layout is
 * the safest fallback for the existing manual remediation commands.
 */
function detectCurrentInstall(scriptPath = process.argv[1] || '') {
    const resolvedScriptPath = resolveScriptPath(scriptPath);
    const pathMatch = inferInstallFromPath(resolvedScriptPath) ?? inferInstallFromPath(scriptPath);
    const packageRoot = findPackageRoot(resolvedScriptPath);
    if (pathMatch) {
        return {
            manager: pathMatch.manager,
            scriptPath,
            resolvedScriptPath,
            packageRoot,
            prefix: pathMatch.prefix,
            detectionSource: 'path',
        };
    }
    if (packageRoot) {
        const packageRootMatch = inferInstallFromPath(packageRoot);
        if (packageRootMatch) {
            return {
                manager: packageRootMatch.manager,
                scriptPath,
                resolvedScriptPath,
                packageRoot,
                prefix: packageRootMatch.prefix,
                detectionSource: 'package-root',
            };
        }
    }
    return {
        manager: 'npm',
        scriptPath,
        resolvedScriptPath,
        packageRoot,
        prefix: null,
        detectionSource: 'default',
    };
}
exports.detectCurrentInstall = detectCurrentInstall;
/**
 * Backward-compatible helper for callers that only need the package manager.
 */
function detectPackageManager(scriptPath = process.argv[1] || '') {
    return detectCurrentInstall(scriptPath).manager;
}
exports.detectPackageManager = detectPackageManager;
function buildPackageManagerEnv(install, baseEnv = process.env) {
    if (!install.prefix) {
        return { ...baseEnv };
    }
    switch (install.manager) {
        case 'npm':
            return {
                ...baseEnv,
                npm_config_prefix: install.prefix,
                NPM_CONFIG_PREFIX: install.prefix,
            };
        case 'yarn':
            return {
                ...baseEnv,
                YARN_GLOBAL_FOLDER: install.prefix,
            };
        case 'pnpm':
            return {
                ...baseEnv,
                PNPM_HOME: install.prefix,
            };
        case 'bun':
            return {
                ...baseEnv,
                BUN_INSTALL: install.prefix,
            };
        default:
            return { ...baseEnv };
    }
}
exports.buildPackageManagerEnv = buildPackageManagerEnv;
function readInstalledPackageVersion(install) {
    return readInstalledPackageState(install).version;
}
exports.readInstalledPackageVersion = readInstalledPackageVersion;
function readFileMtimeMs(filePath) {
    try {
        return fs.statSync(filePath).mtimeMs;
    }
    catch {
        return null;
    }
}
function readInstalledPackageState(install) {
    if (!install.packageRoot) {
        return {
            version: null,
            packageJsonMtimeMs: null,
            scriptMtimeMs: readFileMtimeMs(install.resolvedScriptPath),
        };
    }
    const packageJsonPath = path.join(install.packageRoot, 'package.json');
    const packageJsonMtimeMs = readFileMtimeMs(packageJsonPath);
    const scriptMtimeMs = readFileMtimeMs(install.resolvedScriptPath);
    try {
        const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
        return {
            version: typeof packageJson.version === 'string' ? packageJson.version : null,
            packageJsonMtimeMs,
            scriptMtimeMs,
        };
    }
    catch {
        return {
            version: null,
            packageJsonMtimeMs,
            scriptMtimeMs,
        };
    }
}
exports.readInstalledPackageState = readInstalledPackageState;
function quoteForShell(value) {
    if (/^[A-Za-z0-9_./:-]+$/.test(value)) {
        return value;
    }
    return `'${value.replace(/'/g, `'\\''`)}'`;
}
function quoteForCmd(value) {
    return value.replace(/'/g, "''");
}
function formatWindowsEnvCommand(envVar, value, command) {
    return `powershell -NoProfile -Command "$env:${envVar}='${quoteForCmd(value)}'; ${command}"`;
}
function formatManualUpdateCommand(targetTag, install = detectCurrentInstall(), platform = process.platform) {
    const command = {
        npm: `npm install -g @kaitranntt/ccs@${targetTag}`,
        yarn: `yarn global add @kaitranntt/ccs@${targetTag}`,
        pnpm: `pnpm add -g @kaitranntt/ccs@${targetTag}`,
        bun: `bun add -g @kaitranntt/ccs@${targetTag}`,
    }[install.manager];
    if (!install.prefix) {
        return command;
    }
    const envVar = {
        npm: 'NPM_CONFIG_PREFIX',
        yarn: 'YARN_GLOBAL_FOLDER',
        pnpm: 'PNPM_HOME',
        bun: 'BUN_INSTALL',
    }[install.manager];
    if (platform === 'win32') {
        return formatWindowsEnvCommand(envVar, install.prefix, command);
    }
    return `${envVar}=${quoteForShell(install.prefix)} ${command}`;
}
exports.formatManualUpdateCommand = formatManualUpdateCommand;
//# sourceMappingURL=package-manager-detector.js.map