/**
 * AgentVault one-time setup command.
 *
 * Runs enrollment + waits for owner approval + persists state,
 * then auto-registers the agentvault channel in openclaw config.
 *
 * Usage: npx @agentvault/agentvault setup --token=av_tok_...
 */
import { execSync, spawnSync } from "node:child_process";
import * as readline from "node:readline";
import { resolve } from "node:path";
import { SecureChannel } from "./channel.js";
import { VERSION } from "./index.js";
export async function runSetupCommand(options) {
    const { token, name, apiUrl } = options;
    const dataDir = resolve(options.dataDir.replace(/^~/, process.env.HOME ?? "~"));
    console.log(`
╔══════════════════════════════════════════════╗
║         AgentVault — First-Time Setup        ║
╚══════════════════════════════════════════════╝

  Agent name : ${name}
  Data dir   : ${dataDir}
  API        : ${apiUrl}
`);
    let enrollDone = false;
    const channel = new SecureChannel({
        inviteToken: token,
        dataDir,
        apiUrl,
        agentName: name,
        onMessage: () => { }, // Not handling messages during setup
        onStateChange: (state) => {
            switch (state) {
                case "enrolling":
                    console.log("  Enrolling with AgentVault server...");
                    break;
                case "polling":
                    console.log("  Waiting for approval in your AgentVault dashboard...");
                    if (channel.fingerprint) {
                        console.log(`\n  Fingerprint: ${channel.fingerprint}`);
                        console.log("  Verify this fingerprint matches the one shown in your dashboard");
                        console.log("  before clicking Approve.\n");
                    }
                    break;
                case "activating":
                    console.log("  Approved! Setting up encryption...");
                    break;
                case "ready":
                    enrollDone = true;
                    console.log("  ✅ Enrollment complete! Secure channel established.\n");
                    break;
                case "error":
                    console.error("  ❌ Setup encountered an error.");
                    break;
            }
        },
    });
    channel.on("error", (err) => {
        console.error(`\n  ❌ Setup failed: ${err.message}\n`);
        process.exit(1);
    });
    // Start enrollment — blocks until ready or error
    await new Promise((res, rej) => {
        const check = setInterval(() => {
            if (enrollDone) {
                clearInterval(check);
                res();
            }
        }, 500);
        channel.start().catch((err) => {
            clearInterval(check);
            rej(err);
        });
    });
    // Stop the live connection — OpenClaw's gateway will own it after restart
    await channel.stop();
    // --- Install plugin + register in OpenClaw config ---
    console.log("  Installing AgentVault plugin in OpenClaw...\n");
    // Extend PATH to find openclaw regardless of how npx was invoked
    const home = process.env.HOME ?? "";
    const extraPaths = [
        `${home}/.local/bin`,
        `${home}/.pnpm/bin`,
        `${home}/Library/pnpm/bin`,
        "/usr/local/bin",
        "/opt/homebrew/bin",
    ].join(":");
    const env = { ...process.env, PATH: `${extraPaths}:${process.env.PATH ?? ""}` };
    const pluginInstalled = installPlugin(env);
    if (!pluginInstalled) {
        // openclaw not in PATH — print full manual instructions and bail
        console.log(`
  ⚠️  Could not auto-configure OpenClaw (is 'openclaw' in your PATH?).

  1. Install the plugin:
     openclaw plugins install @agentvault/agentvault

  2. Register the plugin in the allow list:
     openclaw config set plugins.allow '["agentvault"]'

  3. Add this to your OpenClaw config (openclaw.yaml or openclaw.json):
     channels:
       agentvault:
         dataDir: "${dataDir}"
         apiUrl: "${apiUrl}"
         agentName: "${name}"

  4. (Recommended) Install pm2 for auto-restart and crash recovery:
     npm install -g pm2
     pm2 start "openclaw gateway start" --name openclaw-gateway
     pm2 startup
     pm2 save

  5. Restart the gateway:
     openclaw gateway restart
`);
        return;
    }
    console.log("\n  Registering AgentVault channel in OpenClaw config...\n");
    const patchCommands = [
        `openclaw config set channels.agentvault.dataDir "${dataDir}"`,
        `openclaw config set channels.agentvault.apiUrl "${apiUrl}"`,
        `openclaw config set channels.agentvault.agentName "${name}"`,
        `openclaw config set plugins.allow '["agentvault"]'`,
    ];
    let configPatched = false;
    for (const cmd of patchCommands) {
        try {
            execSync(cmd, { stdio: "pipe", env });
            configPatched = true;
        }
        catch {
            // config write failed — fall through to manual
            configPatched = false;
            break;
        }
    }
    if (configPatched) {
        console.log(`  ✅ Channel registered in OpenClaw config.\n`);
        // --- Step 6: Configure pm2 process management ---
        console.log("  Configuring pm2 process management...\n");
        configurePm2(env);
        await promptAndRestart(env);
    }
    else {
        console.log(`  ⚠️  Could not auto-configure OpenClaw channel.
  Add this to your OpenClaw config (openclaw.yaml or openclaw.json) manually:

  channels:
    agentvault:
      dataDir: "${dataDir}"
      apiUrl: "${apiUrl}"
      agentName: "${name}"

  Then restart OpenClaw:
    openclaw gateway restart
`);
    }
}
/**
 * Install/update the plugin in OpenClaw's extensions directory.
 * Returns true if the plugin is installed (or was already up-to-date).
 */
export function installPlugin(env) {
    // Check if already installed
    try {
        const info = execSync("openclaw plugins info agentvault", {
            stdio: "pipe",
            env,
        });
        const infoStr = info.toString();
        const versionMatch = infoStr.match(/version[:\s]+(\S+)/i);
        const installedVersion = versionMatch?.[1];
        if (installedVersion && installedVersion !== VERSION) {
            console.log(`  Updating plugin ${installedVersion} → ${VERSION}...`);
            spawnSync("openclaw", ["plugins", "uninstall", "agentvault"], {
                stdio: "pipe",
                input: "y\n",
                env,
            });
            execSync("openclaw plugins install @agentvault/agentvault", {
                stdio: "pipe",
                env,
            });
            console.log("  ✅ Plugin updated.");
        }
        else {
            console.log(`  Plugin already installed (v${installedVersion ?? "unknown"}).`);
        }
        return true;
    }
    catch {
        // Not installed — install fresh
    }
    try {
        execSync("openclaw plugins install @agentvault/agentvault", {
            stdio: "pipe",
            env,
        });
        console.log("  ✅ Plugin installed in OpenClaw.");
        return true;
    }
    catch {
        console.log("  ⚠️  Could not auto-install plugin.");
        return false;
    }
}
/**
 * Configure pm2 to manage the OpenClaw gateway process.
 * Returns true if pm2 was configured (or already configured).
 */
export function configurePm2(env) {
    // Check if pm2 is available
    try {
        execSync("pm2 --version", { stdio: "pipe", env });
    }
    catch {
        console.log(`
  ℹ️  pm2 not found. For best reliability, install pm2:
     npm install -g pm2

  Then configure the gateway to auto-restart:
     pm2 start "openclaw gateway start" --name openclaw-gateway
     pm2 startup
     pm2 save
`);
        return false;
    }
    // Check if already configured
    try {
        const info = execSync("pm2 describe openclaw-gateway", { stdio: "pipe", env });
        const infoStr = info.toString();
        if (infoStr.includes("online") || infoStr.includes("stopped")) {
            console.log("  pm2 process 'openclaw-gateway' already exists.");
            return true;
        }
    }
    catch {
        // Not configured yet — continue
    }
    // Determine platform-specific command
    const isMac = process.platform === "darwin";
    const startCmd = isMac
        ? "caffeinate -i openclaw gateway start"
        : "openclaw gateway start";
    try {
        execSync(`pm2 start "${startCmd}" --name openclaw-gateway`, { stdio: "pipe", env });
        console.log("  ✅ Gateway registered with pm2.");
    }
    catch (err) {
        console.log(`  ⚠️  Failed to register with pm2: ${err}`);
        return false;
    }
    // Generate startup script
    try {
        execSync("pm2 startup", { stdio: "pipe", env });
        console.log("  ✅ pm2 startup configured (auto-start on boot).");
    }
    catch {
        console.log("  ⚠️  pm2 startup failed — you may need to run 'pm2 startup' manually with sudo.");
    }
    // Save process list
    try {
        execSync("pm2 save", { stdio: "pipe", env });
        console.log("  ✅ pm2 process list saved.");
    }
    catch {
        console.log("  ⚠️  pm2 save failed.");
    }
    return true;
}
/**
 * Prompt the user to restart the OpenClaw gateway now or later.
 * Runs `openclaw gateway restart` synchronously if they confirm.
 */
async function promptAndRestart(env) {
    const answer = await ask("  ⚠️  OpenClaw gateway will restart, briefly interrupting any active conversations.\n" +
        "  Restart now? [y/N] ");
    if (answer.trim().toLowerCase() === "y") {
        console.log("\n  Restarting OpenClaw gateway...");
        const result = spawnSync("openclaw", ["gateway", "restart"], {
            stdio: "inherit",
            env,
        });
        if (result.status === 0) {
            console.log(`
  ✅ Gateway restarted. AgentVault is now active.
  Your AgentVault UI will route encrypted messages
  directly into your agent.
`);
        }
        else {
            console.log(`
  ⚠️  Restart command failed (exit ${result.status ?? "unknown"}).
  Please restart manually:

    openclaw gateway restart
`);
        }
    }
    else {
        console.log(`
  ──────────────────────────────────────────────
  Run this when you're ready to activate:

    openclaw gateway restart

  After restart, your AgentVault UI will route
  encrypted messages directly into your agent.
  ──────────────────────────────────────────────
`);
    }
}
/** Prompt helper — resolves with the user's input line. */
function ask(question) {
    return new Promise((resolve) => {
        const rl = readline.createInterface({
            input: process.stdin,
            output: process.stdout,
            terminal: true,
        });
        rl.question(question, (answer) => {
            rl.close();
            resolve(answer);
        });
    });
}
//# sourceMappingURL=setup.js.map