"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.DAY_SHIFT_SHIM_PATH_ENV = exports.DAY_SHIFT_SHIM_MODE_ENV = void 0;
exports.isVersionManagerShimMode = isVersionManagerShimMode;
exports.isVersionManagerCommand = isVersionManagerCommand;
exports.resolveVersionManagerRoot = resolveVersionManagerRoot;
exports.resolveSelectedManagedCli = resolveSelectedManagedCli;
const node_fs_1 = __importDefault(require("node:fs"));
const node_path_1 = __importDefault(require("node:path"));
const state_layout_1 = require("./state-layout");
exports.DAY_SHIFT_SHIM_MODE_ENV = 'DAY_SHIFT_SHIM_MODE';
exports.DAY_SHIFT_SHIM_PATH_ENV = 'DAY_SHIFT_SHIM_PATH';
function isVersionManagerShimMode(env = process.env) {
    return env[exports.DAY_SHIFT_SHIM_MODE_ENV] === '1' || env[exports.DAY_SHIFT_SHIM_MODE_ENV] === 'true';
}
function isVersionManagerCommand(argv) {
    return argv[2] === 'version';
}
function resolveVersionManagerRoot(env = process.env) {
    return (0, state_layout_1.resolveVersionManagerRoot)({ env });
}
function resolveSelectedManagedCli(options = {}) {
    const env = options.env ?? process.env;
    const versionManagerRoot = resolveVersionManagerRoot(env);
    const selectedMetadataPath = node_path_1.default.join(versionManagerRoot, 'selected-version.json');
    const metadata = readSelectedMetadata(selectedMetadataPath);
    if (!metadata.ok) {
        return metadata;
    }
    const packageRoot = node_path_1.default.join(versionManagerRoot, 'versions', metadata.version, 'package');
    const executableResolution = resolveManagedExecutablePath(packageRoot);
    if (!executableResolution.ok) {
        return executableResolution;
    }
    const recursion = detectRecursionHazard({
        executablePath: executableResolution.executablePath,
        currentExecutablePath: options.currentExecutablePath ?? process.argv[1],
        shimPath: env[exports.DAY_SHIFT_SHIM_PATH_ENV],
    });
    if (recursion !== null) {
        return recursion;
    }
    return {
        ok: true,
        target: {
            versionManagerRoot,
            selectedMetadataPath,
            selectedVersion: metadata.version,
            packageRoot,
            executablePath: executableResolution.executablePath,
        },
    };
}
function readSelectedMetadata(selectedMetadataPath) {
    if (!node_fs_1.default.existsSync(selectedMetadataPath)) {
        return {
            ok: false,
            reason: 'missing-selected-version',
            message: 'No selected Day Shift version is configured.',
            details: [
                `Selected metadata path: ${selectedMetadataPath}`,
                'Configure a selected installed version before using the stable shim.',
            ],
        };
    }
    let parsed;
    try {
        parsed = JSON.parse(node_fs_1.default.readFileSync(selectedMetadataPath, 'utf8'));
    }
    catch (error) {
        return {
            ok: false,
            reason: 'malformed-selected-version-metadata',
            message: 'Selected Day Shift version metadata is malformed.',
            details: [
                `Selected metadata path: ${selectedMetadataPath}`,
                error instanceof Error ? error.message : String(error),
            ],
        };
    }
    if (typeof parsed !== 'object' || parsed === null || !('version' in parsed)) {
        return malformedSelectedMetadata(selectedMetadataPath);
    }
    const version = parsed.version;
    if (typeof version !== 'string' || !/^\d+\.\d+\.\d+$/.test(version)) {
        return malformedSelectedMetadata(selectedMetadataPath);
    }
    return { ok: true, version };
}
function malformedSelectedMetadata(selectedMetadataPath) {
    return {
        ok: false,
        reason: 'malformed-selected-version-metadata',
        message: 'Selected Day Shift version metadata must include an exact stable version.',
        details: [
            `Selected metadata path: ${selectedMetadataPath}`,
            'Expected JSON shape: { "version": "major.minor.patch" }',
        ],
    };
}
function resolveManagedExecutablePath(packageRoot) {
    const packageJsonPath = node_path_1.default.join(packageRoot, 'package.json');
    const candidates = [];
    if (node_fs_1.default.existsSync(packageJsonPath)) {
        try {
            const packageJson = JSON.parse(node_fs_1.default.readFileSync(packageJsonPath, 'utf8'));
            const bin = packageJson?.bin;
            if (typeof bin === 'object' && bin !== null && typeof bin['day-shift'] === 'string') {
                candidates.push(node_path_1.default.join(packageRoot, bin['day-shift']));
            }
            else if (typeof bin === 'string') {
                candidates.push(node_path_1.default.join(packageRoot, bin));
            }
        }
        catch {
            return unsupportedPackageLayout(packageRoot, 'package.json is not valid JSON.');
        }
    }
    candidates.push(node_path_1.default.join(packageRoot, 'bin', process.platform === 'win32' ? 'day-shift.cmd' : 'day-shift'));
    for (const candidate of candidates) {
        if (node_fs_1.default.existsSync(candidate) && node_fs_1.default.statSync(candidate).isFile()) {
            return { ok: true, executablePath: node_path_1.default.resolve(candidate) };
        }
    }
    return unsupportedPackageLayout(packageRoot, 'No managed day-shift executable was found.');
}
function unsupportedPackageLayout(packageRoot, detail) {
    return {
        ok: false,
        reason: 'unsupported-package-layout',
        message: 'Selected Day Shift package layout is unsupported.',
        details: [`Package root: ${packageRoot}`, detail],
    };
}
function detectRecursionHazard(options) {
    const executablePath = realpathIfPresent(options.executablePath);
    const currentExecutablePath = options.currentExecutablePath === undefined ? null : realpathIfPresent(options.currentExecutablePath);
    const shimPath = options.shimPath === undefined || options.shimPath.trim() === '' ? null : realpathIfPresent(options.shimPath);
    if (currentExecutablePath !== null && executablePath === currentExecutablePath) {
        return recursionHazard(options.executablePath, 'managed executable resolves to the current manager entrypoint');
    }
    if (shimPath !== null && executablePath === shimPath) {
        return recursionHazard(options.executablePath, 'managed executable resolves to the stable shim path');
    }
    return null;
}
function recursionHazard(executablePath, detail) {
    return {
        ok: false,
        reason: 'recursion-hazard',
        message: 'Selected Day Shift executable would recurse into the version manager.',
        details: [`Executable path: ${executablePath}`, detail],
    };
}
function realpathIfPresent(inputPath) {
    const resolved = node_path_1.default.resolve(inputPath);
    try {
        return node_fs_1.default.realpathSync(resolved);
    }
    catch {
        return resolved;
    }
}
