// cli/commands/join.js
// clauth join <invite-code>
// Redeems an invite and sets up the vault connection for a new user.
//
// Flow:
//   1. Validate invite code format
//   2. Choose a master password
//   3. Connect to vault (ask for URL + anon key, or use defaults)
//   4. Register machine via Edge Function with invite code
//   5. Optionally install as auto-start service
//   6. Print next-steps

import chalk from "chalk";
import ora from "ora";
import Conf from "conf";
import { getConfOptions } from "../conf-path.js";
import { getMachineHash, deriveSeedHash } from "../fingerprint.js";
import os from "os";

// Default vault — the LIFEAI Supabase project
const DEFAULT_VAULT_URL = "https://uvojezuorjgqzmhhgluu.supabase.co";

export async function runJoin(code) {
  const config = new Conf(getConfOptions());
  const inquirer = (await import("inquirer")).default;

  // ── Validate code format ───────────────────
  const normalized = code.toUpperCase().trim();
  if (!/^[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{4}$/.test(normalized)) {
    console.log(chalk.red("\n  Invalid invite code format. Expected: XXXX-XXXX-XXXX\n"));
    process.exit(1);
  }

  console.log(chalk.cyan(`\n  Joining vault with invite: ${chalk.bold(normalized)}\n`));

  // ── Check for existing installation ────────
  if (config.get("supabase_url")) {
    const { proceed } = await inquirer.prompt([{
      type: "confirm",
      name: "proceed",
      message: "clauth is already configured. Overwrite with new vault connection?",
      default: false,
    }]);
    if (!proceed) {
      console.log(chalk.gray("\n  Cancelled.\n"));
      return;
    }
  }

  // ── Step 1: Choose a password ──────────────
  const { pw } = await inquirer.prompt([{
    type: "password",
    name: "pw",
    message: "Choose a master password (min 8 chars):",
    mask: "*",
    validate: v => v.length >= 8 || "Password must be at least 8 characters",
  }]);
  const { pw2 } = await inquirer.prompt([{
    type: "password",
    name: "pw2",
    message: "Confirm password:",
    mask: "*",
  }]);
  if (pw !== pw2) {
    console.log(chalk.red("\n  Passwords don't match.\n"));
    process.exit(1);
  }

  // ── Step 2: Vault connection details ───────
  // The person who invited you should share the vault URL + anon key.
  // For the LIFEAI vault, the URL is well-known.
  console.log("");
  console.log(chalk.gray("  Your inviter should have shared the vault URL and anon key."));
  console.log(chalk.gray("  Press Enter to use the LIFEAI default vault.\n"));

  const { vaultUrl } = await inquirer.prompt([{
    type: "input",
    name: "vaultUrl",
    message: "Vault URL:",
    default: DEFAULT_VAULT_URL,
  }]);

  const { anonKey } = await inquirer.prompt([{
    type: "input",
    name: "anonKey",
    message: "Vault anon key:",
    validate: v => v.length > 0 || "Anon key is required (ask the person who invited you)",
  }]);

  // ── Step 3: Machine label ─────────────────
  const { label } = await inquirer.prompt([{
    type: "input",
    name: "label",
    message: "Label for this machine:",
    default: os.hostname(),
  }]);

  // ── Step 4: Register machine ───────────────
  const spinner = ora("Registering machine with vault...").start();

  try {
    const machineHash = getMachineHash();
    const seedHash = deriveSeedHash(machineHash, pw);

    const res = await fetch(`${vaultUrl}/functions/v1/auth-vault/register-machine`, {
      method: "POST",
      headers: {
        "Authorization": `Bearer ${anonKey}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        machine_hash: machineHash,
        hmac_seed_hash: seedHash,
        label,
        invite_code: normalized,
      }),
    });

    const body = await res.json().catch(() => ({}));

    if (!res.ok || body.error) {
      const errMsg = body.error || body.message || `HTTP ${res.status}`;
      spinner.fail(chalk.red(`Registration failed: ${errMsg}`));
      console.log("");
      console.log(chalk.yellow("  Possible causes:"));
      console.log(chalk.gray("    - Invite code expired or already used"));
      console.log(chalk.gray("    - Vault URL or anon key incorrect"));
      console.log(chalk.gray("    - Edge Function doesn't support invite-based registration yet"));
      console.log("");
      console.log(chalk.cyan("  Alternative: ask the admin for a bootstrap token, then run:"));
      console.log(chalk.white("    clauth setup --admin-token <token>"));
      console.log("");
      return;
    }

    spinner.succeed(chalk.green(`Machine registered: ${machineHash.slice(0, 12)}...`));

    // Save config
    config.set("supabase_url", vaultUrl);
    config.set("supabase_anon_key", anonKey);

  } catch (err) {
    spinner.fail(chalk.red(`Connection failed: ${err.message}`));
    console.log(chalk.gray("\n  Check your network and vault URL.\n"));
    process.exit(1);
  }

  // ── Step 5: Offer to install as service ────
  const { installService } = await inquirer.prompt([{
    type: "confirm",
    name: "installService",
    message: "Install as auto-start service? (recommended)",
    default: true,
  }]);

  if (installService) {
    try {
      const { runServe } = await import("./serve.js");
      await runServe({ action: "install", pw });
    } catch (err) {
      console.log(chalk.yellow(`\n  Service install skipped: ${err.message}`));
      console.log(chalk.gray("  You can install it later: clauth serve install\n"));
    }
  }

  // ── Step 6: Done ───────────────────────────
  console.log("");
  console.log(chalk.cyan("  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"));
  console.log(chalk.green("  clauth is ready!"));
  console.log(chalk.cyan("  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"));
  console.log("");
  console.log(chalk.gray("  Commands:"));
  console.log(chalk.gray("    clauth test         verify connection"));
  console.log(chalk.gray("    clauth status       list services"));
  console.log(chalk.gray("    clauth get <svc>    retrieve a credential"));
  console.log(chalk.gray("    clauth serve        start daemon"));
  console.log(chalk.gray("    clauth doctor       check health"));
  console.log("");
}
