const chalk = require('chalk');
const UI = require('../utils/ui');
const Routines = require('../utils/routines');
const { listAdapters, getAdapter } = require('../utils/routine-adapters');

const STATUS_BADGE = {
  installed:   chalk.green('● installed'),
  available:   chalk.cyan('○ available'),
  skipped:     chalk.gray('— skipped'),
  disabled:    chalk.gray('× disabled'),
  blocked:     chalk.yellow('! blocked'),
  unavailable: chalk.gray('— unavailable'),
  error:       chalk.red('✗ error')
};

async function list() {
  UI.header('BALDART Routines');

  const routines = new Routines();
  const rows = routines.computeStatus();

  if (rows.length === 0) {
    UI.warning('No routines catalog found. Run `npx baldart update` first.');
    return;
  }

  UI.info(`Catalog: ${rows.length} routines defined.`);
  UI.newline();

  rows.forEach(r => {
    const badge = STATUS_BADGE[r.status] || r.status;
    const cadence = r.spec.schedule && r.spec.schedule.cadence_label
      ? chalk.gray(`[${r.spec.schedule.cadence_label}]`)
      : '';
    console.log(`  ${badge}  ${chalk.bold(r.spec.name)} ${cadence}`);
    console.log(`     ${chalk.gray(r.spec.description || '')}`);
    if (r.lockEntry && r.lockEntry.backend) {
      console.log(`     ${chalk.gray('backend:')} ${r.lockEntry.backend}`);
    }
    if (r.status === 'blocked' && r.requiredArtifacts.missing.length > 0) {
      console.log(`     ${chalk.yellow('missing artifacts:')} ${r.requiredArtifacts.missing.map(m => m.path).join(', ')}`);
    }
    if (r.status === 'error') {
      console.log(`     ${chalk.red('error:')} ${r.error}`);
    }
    UI.newline();
  });

  UI.section('Legend');
  console.log(`  ${STATUS_BADGE.installed}   active in the selected backend (see lock file)`);
  console.log(`  ${STATUS_BADGE.available}   ready to install (\`npx baldart routines install <name>\`)`);
  console.log(`  ${STATUS_BADGE.blocked}     required artifacts missing — install the relevant feature first`);
  console.log(`  ${STATUS_BADGE.skipped}      user opted out (re-prompt with \`routines install <name>\`)`);
  console.log(`  ${STATUS_BADGE.disabled}     previously installed, now disabled`);
  UI.newline();
}

async function install(name) {
  UI.header(`Install routine: ${name}`);

  const routines = new Routines();
  let spec;
  try {
    spec = routines.readSpec(name);
  } catch (err) {
    UI.error(err.message);
    process.exit(1);
  }

  // Show summary
  UI.box(`Routine: ${spec.name}`, [
    spec.description,
    '',
    `Schedule: ${spec.schedule.cron} (${spec.schedule.cadence_label || 'scheduled'}, ${spec.schedule.timezone || 'UTC'})`,
    `Agent:    ${spec.agent}`,
    `Output:   ${(spec.output && spec.output.path) || '(none)'}`,
    `Commit:   ${spec.output && spec.output.commit && spec.output.commit.enabled ? 'yes (' + spec.output.commit.prefix + ')' : 'no'}`
  ]);

  // Check artifacts
  const status = routines.computeStatus().find(r => r.spec.name === name);
  if (status && status.requiredArtifacts.missing.length > 0) {
    if (spec.optional) {
      UI.warning(`Optional routine — required artifacts missing: ${status.requiredArtifacts.missing.map(m => m.path).join(', ')}`);
      const proceed = await UI.confirm('Install anyway?', false);
      if (!proceed) {
        UI.info('Aborted.');
        return;
      }
    } else {
      UI.error(`Required artifacts missing — cannot install:`);
      status.requiredArtifacts.missing.forEach(m => console.log('  • ' + m.path));
      process.exit(1);
    }
  }

  // Pick adapter
  const choices = listAdapters().map(n => {
    const adapter = getAdapter(n);
    return { name: `${adapter.label} — ${adapter.description}`, value: n };
  });
  choices.push({ name: 'Cancel (do nothing)', value: '__cancel' });

  const backend = await UI.select('Which scheduling backend?', choices);
  if (backend === '__cancel') {
    UI.info('Aborted.');
    return;
  }

  // Install
  const adapter = getAdapter(backend);
  const result = adapter.install(spec);

  routines.setLockEntry(name, {
    status: 'installed',
    backend: backend,
    since_version: spec.since_version || null,
    artifacts: result.artifacts || []
  });

  UI.success(`Routine "${name}" installed via ${adapter.label}.`);
  if (result.artifacts && result.artifacts.length > 0) {
    UI.section('Generated artifacts');
    result.artifacts.forEach(a => console.log('  • ' + a));
  }
  if (result.followup && result.followup.length > 0) {
    UI.section('Follow-up steps');
    result.followup.forEach(l => console.log('  ' + l));
  }
  UI.newline();
}

async function disable(name) {
  UI.header(`Disable routine: ${name}`);

  const routines = new Routines();
  const lock = routines.readLock();
  const entry = (lock.routines || {})[name];

  if (!entry || entry.status !== 'installed') {
    UI.warning(`Routine "${name}" is not currently installed.`);
    return;
  }

  let adapter;
  try { adapter = getAdapter(entry.backend); }
  catch (err) { UI.warning(`Unknown backend in lock: ${entry.backend}. Removing lock entry only.`); }

  if (adapter) {
    const result = adapter.uninstall(name);
    if (result.followup && result.followup.length > 0) {
      UI.section('Manual cleanup steps');
      result.followup.forEach(l => console.log('  ' + l));
    }
  }

  routines.setLockEntry(name, { status: 'disabled' });
  UI.success(`Routine "${name}" disabled.`);
}

async function doctor() {
  UI.header('Routines health check');

  const routines = new Routines();
  const rows = routines.computeStatus();
  let problems = 0;

  rows.forEach(r => {
    if (r.status === 'installed' && r.lockEntry) {
      let adapter;
      try { adapter = getAdapter(r.lockEntry.backend); }
      catch (err) {
        UI.error(`${r.spec.name}: unknown backend in lock — ${r.lockEntry.backend}`);
        problems++;
        return;
      }
      const present = adapter.detect(r.spec.name);
      if (!present) {
        UI.error(`${r.spec.name}: lock says installed via ${r.lockEntry.backend} but artifact is missing.`);
        problems++;
      } else {
        UI.success(`${r.spec.name}: OK (${r.lockEntry.backend})`);
      }
    } else if (r.status === 'blocked') {
      UI.warning(`${r.spec.name}: blocked — missing ${r.requiredArtifacts.missing.map(m => m.path).join(', ')}`);
      problems++;
    } else if (r.status === 'error') {
      UI.error(`${r.spec.name}: spec error — ${r.error}`);
      problems++;
    }
  });

  UI.newline();
  if (problems === 0) {
    UI.success('All routines healthy.');
  } else {
    UI.warning(`Found ${problems} problem(s). Run \`npx baldart routines install <name>\` to re-install or \`disable <name>\` to clean up.`);
  }
}

/**
 * Wizard meant to be called after `add` / `update` succeeds.
 * Surfaces routines the user has never been prompted about and offers to
 * install them. Non-interactive when stdin is not a TTY (silently exits).
 */
async function postUpdateWizard() {
  if (!process.stdin.isTTY) return;

  const routines = new Routines();
  const newOnes = routines.newRoutines();

  if (newOnes.length === 0) return;

  UI.newline();
  UI.section('New routines available');
  UI.info(`BALDART ships ${newOnes.length} scheduled routine(s) you haven't reviewed yet.`);
  UI.info('These are the schedules that make the framework\'s auto-learning / drift loops actually run.');
  UI.newline();

  newOnes.forEach(r => {
    const cadence = r.spec.schedule && r.spec.schedule.cadence_label
      ? `[${r.spec.schedule.cadence_label} — ${r.spec.schedule.cron}]`
      : '';
    console.log(`  • ${chalk.bold(r.spec.name)} ${chalk.gray(cadence)}`);
    console.log(`    ${chalk.gray(r.spec.description)}`);
  });
  UI.newline();

  const proceed = await UI.confirm('Configure these routines now?', true);
  if (!proceed) {
    // Mark them all as skipped so we don't ask again on the next update.
    newOnes.forEach(r => routines.setLockEntry(r.spec.name, { status: 'skipped' }));
    UI.info('Skipped. Run `npx baldart routines list` to revisit.');
    return;
  }

  for (const r of newOnes) {
    const choice = await UI.select(`Routine "${r.spec.name}" — what now?`, [
      { name: 'Install with Claude Code Cloud (RemoteTrigger)', value: 'claude-code-cloud' },
      { name: 'Install with GitHub Actions',                   value: 'github-actions' },
      { name: 'Install with local cron',                       value: 'cron' },
      { name: 'Skip (don\'t ask again unless I run `routines install`)', value: '__skip' },
      { name: 'Decide later (ask me again next update)',       value: '__later' }
    ]);

    if (choice === '__later') continue;
    if (choice === '__skip') {
      routines.setLockEntry(r.spec.name, { status: 'skipped' });
      continue;
    }

    const adapter = getAdapter(choice);
    const result = adapter.install(r.spec);
    routines.setLockEntry(r.spec.name, {
      status: 'installed',
      backend: choice,
      since_version: r.spec.since_version || null,
      artifacts: result.artifacts || []
    });
    UI.success(`Installed ${r.spec.name} via ${adapter.label}.`);
    if (result.followup && result.followup.length > 0) {
      UI.section('Follow-up');
      result.followup.forEach(l => console.log('  ' + l));
    }
    UI.newline();
  }
}

module.exports = { list, install, disable, doctor, postUpdateWizard };
