/**
 * `madarx setup` — interactive first-run wizard.
 *
 * An arrow-key guided setup that decides the things that shape the whole
 * install up front, then fills in credentials and preferences:
 *
 *   1. Usage mode      personal (local-only) vs team (Supabase shared layer)
 *   2. Main agent      which model/engine the orchestrator runs on
 *   3. Sub-agents      default model/engine new agents inherit
 *   4. Secrets vault   master key (generated + persisted on first run)
 *   5. API keys        Anthropic / OpenAI → encrypted vault
 *   6. Folder grants   MADARX_ALLOWED_ROOTS (the agent's file/exec boundary)
 *   7. WhatsApp        bridge on/off
 *   8. Auto-update     weekly notify / hands-off / off
 *
 * Sets MADARX_DISABLE_INPROC_DAEMON=1 before importing the runtime — a setup run
 * must not spin up cron/heartbeat loops.
 */

import { createInterface } from 'node:readline/promises';
import { applyHomeEnv } from './home.js';
import { upsertEnvVar, removeEnvVar, readEnvFile } from './env-file.js';
import { renderHeader, _palette as P, fg, bold, dim } from './banner.js';
import { readVersion } from './dispatch.js';
import { select, confirm } from './prompt.js';

function isInteractive() {
  return Boolean(process.stdin.isTTY && process.stdout.isTTY);
}

const h2 = (s) => console.log('\n' + bold(fg(P.platinum, s)));
const note = (s) => console.log('  ' + dim(fg(P.muted, s)));
const ok = (s) => console.log('  ' + fg(P.mars, '●') + ' ' + fg(P.bone, s));

/** Open an ephemeral readline for one text prompt, then close it (so it never
 *  competes with the raw-mode arrow menus). `secret` echoes `*`. */
async function ask(prompt, { dflt = '', secret = false } = {}) {
  const rl = createInterface({ input: process.stdin, output: process.stdout, terminal: true });
  rl.stdoutMuted = false;
  rl._writeToOutput = function (str) { rl.output.write(rl.stdoutMuted ? '*' : str); };
  try {
    rl.stdoutMuted = secret;
    const suffix = dflt ? ` [${dflt}]` : '';
    const ans = (await rl.question(`  ${fg(P.bone, prompt)}${dim(suffix)}: `)).trim();
    if (secret) rl.output.write('\n');
    return ans || dflt;
  } finally {
    rl.close();
  }
}

export async function setup() {
  if (!isInteractive()) {
    console.error('madarx setup needs an interactive terminal (TTY). Run it directly in your shell.');
    return 1;
  }

  process.env.MADARX_DISABLE_INPROC_DAEMON = '1'; // management command — no daemons
  const layout = applyHomeEnv();

  try {
    console.log(renderHeader('setup', readVersion()));
    console.log(`Data home: ${fg(P.bone, layout.home)}`);
    note('override anytime with the MADARX_HOME env var');

    // Open the DB once so vault + config tables exist for the steps below.
    const { getDb } = await import('../db.js');
    getDb();
    const { setConfig } = await import('../config.js');

    // ── 1. Usage mode ────────────────────────────────────────────────────────
    h2('1 · How will you use madarX?');
    const mode = await select('Choose a setup', [
      { label: 'Personal', value: 'local', tag: 'recommended', hint: 'local-only, everything on this machine' },
      { label: 'Team', value: 'supabase', hint: 'shared with a team via Supabase (auth, orgs, sharing)' },
    ], { default: 0 });

    if (mode === 'supabase') {
      setConfig('auth_mode', 'supabase');
      note('Enter your Supabase project credentials (stored in ' + layout.envFile + ').');
      const existing = readEnvFile(layout.envFile);
      const url = await ask('Supabase URL', { dflt: existing.SUPABASE_URL || existing.NEXT_PUBLIC_SUPABASE_URL || '' });
      const anon = await ask('Supabase anon key', { dflt: existing.SUPABASE_ANON_KEY || '' });
      const service = await ask('Supabase service-role key', { secret: true });
      if (url) { upsertEnvVar(layout.envFile, 'SUPABASE_URL', url); upsertEnvVar(layout.envFile, 'NEXT_PUBLIC_SUPABASE_URL', url); }
      if (anon) { upsertEnvVar(layout.envFile, 'SUPABASE_ANON_KEY', anon); upsertEnvVar(layout.envFile, 'NEXT_PUBLIC_SUPABASE_ANON_KEY', anon); }
      if (service) upsertEnvVar(layout.envFile, 'SUPABASE_SERVICE_ROLE_KEY', service);
      ok('Team mode (Supabase) configured.');
      note('Apply the cloud schema once: see supabase/README.md.');
    } else {
      setConfig('auth_mode', 'local');
      ok('Personal mode — local-only.');
    }

    // ── Model catalog (probes installed CLIs + Ollama; Anthropic always listed) ─
    const { getModels, setModel, getModel } = await import('../agent-config.js');
    const { defaultModelForEngine } = await import('../agent-engines.js');
    let models = [];
    try { models = await getModels(); } catch { models = []; }
    const recommendedId = models.find((m) => m.engine === 'claude-code') ? 'claude-code'
      : (models.find((m) => m.id === 'claude-sonnet-4-6') ? 'claude-sonnet-4-6' : models[0]?.id);
    const modelOption = (m) => ({
      label: m.label,
      value: { id: m.id, engine: m.engine },
      hint: m.engine,
      tag: m.id === recommendedId ? 'recommended' : undefined,
    });
    const orderedModels = [
      ...models.filter((m) => m.id === recommendedId),
      ...models.filter((m) => m.id !== recommendedId),
    ];

    // ── 2. Main agent model ──────────────────────────────────────────────────
    h2('2 · Main agent model');
    note('the orchestrator that plans your work and dispatches sub-agents');
    const current = getModel();
    const mainChoice = await select('Select the main agent model', [
      ...orderedModels.map(modelOption),
      { label: `Keep current (${current})`, value: { keep: true } },
    ], { default: 0 });
    if (!mainChoice.keep) { setModel(mainChoice.id); ok(`Main agent → ${mainChoice.id}`); }
    else ok(`Main agent unchanged (${current})`);
    const mainEngine = mainChoice.keep ? null : mainChoice.engine;

    // ── 3. Sub-agent default model ───────────────────────────────────────────
    h2('3 · Sub-agent default model');
    note('what newly created agents inherit unless you pick another at creation');
    const subChoice = await select('Select the default sub-agent model', [
      { label: 'Same as main agent', value: { same: true }, tag: 'recommended' },
      ...orderedModels.map(modelOption),
    ], { default: 0 });
    let subEngine, subModel;
    if (subChoice.same) {
      subEngine = mainEngine || (orderedModels.find((m) => m.id === current)?.engine) || 'claude-code';
      subModel = mainChoice.keep ? current : mainChoice.id;
    } else {
      subEngine = subChoice.engine;
      subModel = subChoice.engine === 'anthropic' ? subChoice.id : defaultModelForEngine(subChoice.engine);
    }
    setConfig('default_agent_engine', subEngine);
    setConfig('default_agent_model', subModel);
    ok(`Sub-agents → ${subEngine}${subModel ? ' · ' + subModel : ''}`);

    // ── 4. Secrets vault master key ──────────────────────────────────────────
    h2('4 · Secrets vault');
    const { resolveMasterKey } = await import('../master-key.js');
    resolveMasterKey({ allowGenerate: true });
    ok('Master key ready (AES-256-GCM).');

    // ── 5. API keys → encrypted vault ────────────────────────────────────────
    h2('5 · API keys');
    note('stored encrypted in the vault · press Enter to skip any');
    const { setSecret, getSecret } = await import('../secrets.js');
    const usesAnthropic = [mainEngine, subEngine].includes('anthropic');
    const keyPrompts = [
      ['ANTHROPIC_API_KEY', 'Anthropic API key (Claude)' + (usesAnthropic ? ' — required for your selection' : '')],
      ['OPENAI_API_KEY', 'OpenAI API key (voice/realtime, optional)'],
    ];
    for (const [name, label] of keyPrompts) {
      let have = false;
      try { have = Boolean(getSecret(name)); } catch { /* vault may be empty */ }
      const val = await ask(label + (have ? ' (set — Enter to keep)' : ''), { secret: true });
      if (val) {
        try { setSecret(name, val, { scope: 'global' }); ok(`Stored ${name}.`); }
        catch (err) { console.error('  ' + fg(P.mars, '✗') + ` Could not store ${name}: ${err.message}`); }
      }
    }

    // ── 6. Folder permissions ────────────────────────────────────────────────
    h2('6 · Folder permissions');
    note('the agent can read/write/run ONLY inside roots you grant (repo + workspace/ always allowed)');
    const existingRoots = readEnvFile(layout.envFile).MADARX_ALLOWED_ROOTS || '';
    const roots = await ask('Extra allowed roots (comma-separated absolute paths)', { dflt: existingRoots });
    if (roots) {
      const cleaned = roots.split(',').map((r) => r.trim()).filter(Boolean).join(',');
      upsertEnvVar(layout.envFile, 'MADARX_ALLOWED_ROOTS', cleaned);
      ok(`Granted: ${cleaned}`);
    } else {
      note('no extra roots granted');
    }

    // ── 7. WhatsApp bridge ───────────────────────────────────────────────────
    h2('7 · WhatsApp bridge');
    const enableWa = await confirm('Run the WhatsApp bridge with `madarx`?', { default: true });
    if (enableWa) { removeEnvVar(layout.envFile, 'MADARX_DISABLE_WHATSAPP'); ok('Enabled — idles until you pair a dedicated number.'); }
    else { upsertEnvVar(layout.envFile, 'MADARX_DISABLE_WHATSAPP', '1'); ok('Disabled.'); }

    // ── 8. Auto-update ───────────────────────────────────────────────────────
    h2('8 · Auto-update');
    const upd = await select('How should madarX handle updates?', [
      { label: 'Notify weekly', value: 'notify', tag: 'recommended', hint: 'check weekly, tell me — I apply' },
      { label: 'Auto-apply weekly', value: 'auto', hint: 'hands-off, gated by the approval/trust tier' },
      { label: 'Off', value: 'off', hint: 'I will run `madarx update` myself' },
    ], { default: 0 });
    if (upd === 'off') { setConfig('auto_update_mode', 'off'); ok('Auto-update off.'); }
    else {
      setConfig('auto_update_mode', 'weekly');
      setConfig('auto_update_apply', upd === 'auto' ? 'auto' : 'notify');
      ok(`Weekly check on — ${upd === 'auto' ? 'auto-apply' : 'notify only'}.`);
    }

    console.log('\n' + bold(fg(P.platinum, 'Setup complete.')) + '  Start everything with:  ' + fg(P.mars, 'madarx') + '\n');
    return 0;
  } catch (err) {
    console.error(`\nsetup failed: ${err?.stack || err}`);
    return 1;
  }
}
