// engine/version-detector/bundled-version-checker.ts — SPEC-756
// Detects when Planu is running as a bundled version inside another plugin (e.g. Superpowers)
// and compares it against the latest published version on npm.
import { PLANU_VERSION } from '../../config/version.js';
const NPM_REGISTRY_URL = 'https://registry.npmjs.org/@planu/cli/latest';
const PACKAGE_NAME = '@planu/cli';
// ---------------------------------------------------------------------------
// Public API
// ---------------------------------------------------------------------------
/**
 * Returns the current running version of Planu from package.json.
 */
export function getCurrentVersion() {
    return PLANU_VERSION;
}
/**
 * Fetches the latest published version from the npm registry.
 * Returns null on any network or parse error.
 */
export async function fetchLatestNpmVersion(packageName, timeoutMs) {
    const url = packageName === PACKAGE_NAME
        ? NPM_REGISTRY_URL
        : `https://registry.npmjs.org/${packageName}/latest`;
    try {
        const controller = new AbortController();
        const timerId = setTimeout(() => {
            controller.abort();
        }, timeoutMs);
        let response;
        try {
            response = await fetch(url, { signal: controller.signal });
        }
        finally {
            clearTimeout(timerId);
        }
        if (!response.ok) {
            return null;
        }
        const body = await response.json();
        if (typeof body === 'object' && body !== null && 'version' in body) {
            const v = body.version;
            if (typeof v === 'string' && v.length > 0) {
                return v;
            }
        }
        return null;
    }
    catch {
        return null;
    }
}
/**
 * Parses a semver string into [major, minor, patch] tuple.
 * Returns [0, 0, 0] on invalid input.
 */
function parseSemver(version) {
    // Strip leading 'v' if present
    const clean = version.startsWith('v') ? version.slice(1) : version;
    const parts = clean.split('.').map((p) => parseInt(p, 10));
    /* c8 ignore next 3 — `?? 0` fallback is unreachable when isFinite is true (noUncheckedIndexedAccess artifact) */
    const major = Number.isFinite(parts[0]) ? (parts[0] ?? 0) : 0;
    const minor = Number.isFinite(parts[1]) ? (parts[1] ?? 0) : 0;
    const patch = Number.isFinite(parts[2]) ? (parts[2] ?? 0) : 0;
    return [major, minor, patch];
}
/**
 * Returns true if latest > current by at least 1 minor version.
 * e.g. current=1.0.2, latest=2.4.0 → true
 *      current=2.4.0, latest=2.4.1 → false (only patch diff)
 *      current=2.3.0, latest=2.4.0 → true
 */
export function hasVersionGap(current, latest) {
    const [cMaj, cMin] = parseSemver(current);
    const [lMaj, lMin] = parseSemver(latest);
    if (lMaj > cMaj) {
        return true;
    }
    if (lMaj === cMaj && lMin > cMin) {
        return true;
    }
    return false;
}
/**
 * High-level helper: checks if the running Planu is behind npm by at least 1 minor version.
 * Returns { gap: true, current, latest } or { gap: false } or { gap: false } on network failure.
 */
export async function checkBundledVersionGap(timeoutMs = 2000) {
    const current = getCurrentVersion();
    const latest = await fetchLatestNpmVersion(PACKAGE_NAME, timeoutMs);
    if (latest === null) {
        return { gap: false };
    }
    if (hasVersionGap(current, latest)) {
        return { gap: true, current, latest };
    }
    return { gap: false };
}
//# sourceMappingURL=bundled-version-checker.js.map