"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;
    }
}
