import { spawn, spawnSync, execSync } from 'child_process';
import { readFileSync } from 'fs';
import { join, sep } from 'path';
import { fileURLToPath } from 'url';
import { t } from './i18n.js';
import { CLI_VERSION } from './cli-version.js';
import { assertCliVersionAllowed, fetchRemoteVersionPolicy, } from './version-check.js';
import { isVersionAtLeast } from './semver.js';
import { resolveCursorconnectBin } from './macos-autostart.js';
const UPDATE_ATTEMPTED_ENV = 'CURSORCONNECT_UPDATE_ATTEMPTED';
/** Установка через `npm i -g cursorconnect` (не dev из клона). */
export function isGlobalNpmInstall() {
    const self = fileURLToPath(import.meta.url);
    if (self.includes(`${sep}node_modules${sep}cursorconnect${sep}`))
        return true;
    try {
        const bin = resolveCursorconnectBin();
        return bin.includes(`${sep}node_modules${sep}cursorconnect${sep}`);
    }
    catch {
        return false;
    }
}
export function isAutoUpdateDisabled(argv) {
    if (process.env.CURSORCONNECT_NO_AUTO_UPDATE === '1')
        return true;
    return argv.includes('--no-auto-update');
}
export function canAutoUpdateCli(argv) {
    return isGlobalNpmInstall() && !isAutoUpdateDisabled(argv);
}
function resolveNpmBin() {
    try {
        return execSync('command -v npm', {
            encoding: 'utf-8',
            shell: '/bin/bash',
        }).trim();
    }
    catch {
        return 'npm';
    }
}
export function installLatestGlobal() {
    const npm = resolveNpmBin();
    const r = spawnSync(npm, ['install', '-g', 'cursorconnect@latest'], {
        stdio: 'inherit',
        env: process.env,
    });
    return r.status === 0;
}
export function reexecCursorconnect(subcommand, restArgv) {
    const bin = resolveCursorconnectBin();
    const args = [
        subcommand,
        ...restArgv.filter((a) => a !== '--no-auto-update'),
    ];
    return new Promise(() => {
        const child = spawn(bin, args, {
            stdio: 'inherit',
            env: {
                ...process.env,
                [UPDATE_ATTEMPTED_ENV]: '1',
            },
        });
        child.on('error', (e) => {
            console.error(t('version.reexecFailed', { error: String(e) }));
            process.exit(1);
        });
        child.on('exit', (code, signal) => {
            if (signal)
                process.exit(1);
            process.exit(code ?? 0);
        });
    });
}
function readGlobalInstalledCliVersion() {
    try {
        const root = execSync('npm root -g', {
            encoding: 'utf-8',
            shell: '/bin/bash',
        }).trim();
        const pkg = JSON.parse(readFileSync(join(root, 'cursorconnect', 'package.json'), 'utf-8'));
        return pkg.version?.trim() || CLI_VERSION;
    }
    catch {
        return CLI_VERSION;
    }
}
export async function cmdUpdateGlobal() {
    if (!isGlobalNpmInstall()) {
        console.error(t('version.updateDevOnly'));
        process.exit(1);
    }
    console.log(t('version.manualUpdating', { current: CLI_VERSION }));
    if (!installLatestGlobal()) {
        console.error(t('version.updateFailed'));
        process.exit(1);
    }
    console.log(t('version.updateDone', { version: readGlobalInstalledCliVersion() }));
}
/**
 * Проверка min на relay; при global npm и current &lt; latest — `npm i -g` и re-exec.
 */
export async function ensureCliVersionForRelay(relayUrl, opts) {
    const policy = await fetchRemoteVersionPolicy(relayUrl);
    if (!policy?.minCliVersion) {
        console.warn(t('version.policyFetchFailed'));
        return;
    }
    const argv = opts?.argv ?? [];
    const subcommand = opts?.subcommand ?? 'start';
    const attempted = process.env[UPDATE_ATTEMPTED_ENV] === '1';
    if (attempted) {
        assertCliVersionAllowed(policy);
        if (!isVersionAtLeast(CLI_VERSION, policy.latestCliVersion)) {
            console.warn(t('version.stillBehindLatest', {
                current: CLI_VERSION,
                latest: policy.latestCliVersion,
                command: policy.updateCliCommand,
            }));
        }
        return;
    }
    const belowMin = !isVersionAtLeast(CLI_VERSION, policy.minCliVersion);
    const behindLatest = !isVersionAtLeast(CLI_VERSION, policy.latestCliVersion);
    const needsUpgrade = belowMin || behindLatest;
    if (needsUpgrade && canAutoUpdateCli(argv)) {
        const target = behindLatest ? policy.latestCliVersion : policy.minCliVersion;
        console.log(t('version.autoUpdating', {
            current: CLI_VERSION,
            latest: target,
        }));
        if (installLatestGlobal()) {
            await reexecCursorconnect(subcommand, argv);
            return;
        }
        console.warn(t('version.autoUpdateFailed'));
    }
    assertCliVersionAllowed(policy);
}
