const fs = require('fs');
const path = require('path');
const chalk = require('chalk');
const UI = require('../utils/ui');
const SymlinkUtils = require('../utils/symlinks');

/**
 * `npx baldart migrate` — fixes installation state on existing repos.
 *
 * Today handles two known migration paths:
 *
 *   1. **v1.x → v2.1.1**: no `.claude/skills/` directory existed; the v2.0.x
 *      update tried to install a bulk symlink and (depending on the user's
 *      state) may have renamed their existing skills directory to
 *      `.claude/skills.backup`. We surface that, convert to per-item layout,
 *      and offer to restore the backup contents alongside framework skills.
 *
 *   2. **v2.0.x → v2.1.1**: the v2.0.x bulk symlink at `.claude/skills` is
 *      replaced with a real directory + per-item framework skill symlinks.
 *      Any user skills that ended up in `.claude/skills.backup` are restored
 *      into the new directory (with name-collision detection).
 *
 * The command is idempotent: running it on an already-migrated repo simply
 * reports "nothing to do".
 */
async function migrate() {
  UI.header('BALDART Migration');

  const cwd = process.cwd();
  const symlinks = new SymlinkUtils(cwd);

  const skillsPath = path.join(cwd, '.claude', 'skills');
  const skillsBackup = path.join(cwd, '.claude', 'skills.backup');
  const frameworkDir = path.join(cwd, '.framework');
  const frameworkSkillsDir = path.join(frameworkDir, 'framework', '.claude', 'skills');

  // --- Pre-flight ---------------------------------------------------------

  if (!fs.existsSync(frameworkDir)) {
    UI.error('No `.framework/` directory found. BALDART is not installed in this repo.');
    UI.info('Run `npx baldart add` first.');
    return;
  }

  if (!fs.existsSync(frameworkSkillsDir)) {
    UI.warning('Framework appears to be older than v2.0.0 (no skills directory). Run `npx baldart update` first.');
    return;
  }

  // --- Inspect current state ---------------------------------------------

  UI.section('Inspecting current installation');

  let skillsState = 'none';                  // none | bulk-symlink | real-dir
  let backupPresent = false;

  if (fs.existsSync(skillsPath)) {
    const stat = fs.lstatSync(skillsPath);
    if (stat.isSymbolicLink()) {
      skillsState = 'bulk-symlink';
      const linkTarget = fs.readlinkSync(skillsPath);
      UI.warning(`.claude/skills is a legacy bulk symlink → ${linkTarget}`);
    } else {
      skillsState = 'real-dir';
      const entries = fs.readdirSync(skillsPath);
      UI.info(`.claude/skills/ is a real directory with ${entries.length} entries.`);
    }
  } else {
    UI.info('.claude/skills/ does not exist yet.');
  }

  if (fs.existsSync(skillsBackup)) {
    backupPresent = true;
    const entries = fs.readdirSync(skillsBackup).filter(n => !n.startsWith('.'));
    UI.warning(`Found .claude/skills.backup with ${entries.length} entries (from a prior failed update).`);
  }

  // --- Plan ---------------------------------------------------------------

  const actions = [];
  if (skillsState === 'bulk-symlink') {
    actions.push('Replace legacy bulk symlink with a real directory (.claude/skills/).');
  }
  if (skillsState === 'none') {
    actions.push('Create .claude/skills/ as a real directory.');
  }
  actions.push('Merge framework skills as per-item symlinks (existing user skills preserved).');
  if (backupPresent) {
    actions.push('Restore user skills from .claude/skills.backup into .claude/skills/ (no overwrites).');
  }
  actions.push('Record any name collisions in .baldart/skill-conflicts.json.');

  UI.section('Planned actions');
  UI.list(actions);
  UI.newline();

  const proceed = await UI.confirm('Proceed with migration?', true);
  if (!proceed) {
    UI.info('Aborted. No changes made.');
    return;
  }

  // --- Step 1: convert bulk symlink → real directory ---------------------

  if (skillsState === 'bulk-symlink') {
    UI.section('Step 1: convert legacy bulk symlink');
    fs.unlinkSync(skillsPath);
    fs.mkdirSync(skillsPath, { recursive: true });
    UI.success('Replaced bulk symlink with empty real directory.');
  } else if (skillsState === 'none') {
    fs.mkdirSync(skillsPath, { recursive: true });
    UI.success('Created .claude/skills/ directory.');
  }

  // --- Step 2: per-item framework skill merge ----------------------------

  UI.section('Step 2: merge framework skills (per-item)');
  // Read tools from config so migrate honors the user's per-tool selection.
  let enabledTools = ['claude'];
  try {
    const yaml = require('js-yaml');
    const cfgPath = path.join(cwd, 'baldart.config.yml');
    if (fs.existsSync(cfgPath)) {
      const cfg = yaml.load(fs.readFileSync(cfgPath, 'utf8'));
      if (Array.isArray(cfg?.tools?.enabled) && cfg.tools.enabled.length) {
        enabledTools = cfg.tools.enabled;
      }
    }
  } catch (_) { /* keep default */ }
  const mergeResult = symlinks.mergeSkills({ tools: enabledTools });
  // v3.8.0+: also per-item merge agents and commands (was bulk symlink before).
  symlinks.mergeAgents({ tools: enabledTools });
  symlinks.mergeCommands({ tools: enabledTools });
  UI.info(`Linked ${mergeResult.linked.length} framework skills, kept ${mergeResult.skipped.length} as-is, ${mergeResult.conflicts.length} conflict(s).`);

  // --- Step 3: restore user skills from .backup --------------------------

  if (backupPresent) {
    UI.section('Step 3: restore user skills from .backup');
    const entries = fs.readdirSync(skillsBackup).filter(n => !n.startsWith('.'));
    let restored = 0;
    let collided = 0;

    entries.forEach(name => {
      const src = path.join(skillsBackup, name);
      const dst = path.join(skillsPath, name);

      if (fs.existsSync(dst)) {
        const stat = fs.lstatSync(dst);
        if (stat.isSymbolicLink()) {
          // Framework symlink already there — name collision
          UI.warning(`Collision: backup has "${name}" but framework also ships it. Backup kept at .claude/skills.backup/${name}.`);
          collided++;
          return;
        }
      }

      // Move (atomic rename) from backup into skills/
      fs.renameSync(src, dst);
      UI.success(`Restored user skill: .claude/skills/${name}`);
      restored++;
    });

    // Remove the backup dir if empty
    const remaining = fs.readdirSync(skillsBackup).filter(n => !n.startsWith('.'));
    if (remaining.length === 0) {
      fs.rmSync(skillsBackup, { recursive: true, force: true });
      UI.success('Removed empty .claude/skills.backup.');
    } else {
      UI.warning(`${remaining.length} item(s) still in .claude/skills.backup (collisions kept for manual review).`);
    }

    UI.info(`Restored ${restored} user skill(s). ${collided} collision(s) left in .backup.`);
  }

  // --- Step 4: report ----------------------------------------------------

  UI.newline();
  UI.header('✓ MIGRATION COMPLETE');

  const summaryLines = [
    `Framework skills linked: ${mergeResult.linked.length}`,
    `Existing user skills kept: ${mergeResult.skipped.filter(s => s.reason !== 'already-linked').length}`,
    `Name collisions recorded: ${mergeResult.conflicts.length}`
  ];
  if (backupPresent) {
    summaryLines.push('.claude/skills.backup processed (see warnings above).');
  }
  UI.box('Migration summary', summaryLines);

  UI.section('Next steps');
  UI.list([
    'Run `npx baldart routines list` to review schedule status (v2.1.0+).',
    'Run `npx baldart status` for an overall installation check.',
    'Commit the resulting changes (`.claude/skills/`, `.baldart/skill-conflicts.json` if any) so the team sees the same state.'
  ]);
  UI.newline();
}

module.exports = migrate;
