#!/usr/bin/env node
/**
 * migrate-hermes-home.js — One-shot migration for HERMES_HOME path change.
 *
 * Background: HERMES_HOME was previously computed from process.cwd() which
 * produced different paths depending on where the runner was launched from.
 * Starting with Overmind 2.8.27, HERMES_HOME is resolved from
 * OVERMIND_AGENT_HOME or $HOME/.overmind/hermes/agent_<name>/.hermes.
 *
 * This script migrates any existing state from the legacy workspace-relative
 * paths (e.g. <workflow>/.overmind/hermes/agent_<name>/) to the new canonical
 * HOME-based path. Safe to run multiple times.
 *
 * Usage:  node scripts/migrate-hermes-home.js [--dry-run]
 */

import fs from 'fs';
import path from 'path';
import os from 'os';

const args = process.argv.slice(2);
const dryRun = args.includes('--dry-run');

function log(msg) {
  process.stdout.write(`[migrate-hermes-home] ${msg}\n`);
}

function findLegacyBases(workspaceDir) {
  const legacy = [];
  for (const sub of ['.overmind/hermes', '.overmind/hermes/agent_*']) {
    const full = path.join(workspaceDir, sub);
    if (fs.existsSync(full)) {
      try {
        const entries = fs.readdirSync(full, { withFileTypes: true });
        for (const e of entries) {
          if (e.isDirectory() && e.name.startsWith('agent_')) {
            legacy.push(path.join(full, e.name));
          } else if (e.isDirectory() && e.name === 'central') {
            legacy.push(path.join(full, e.name));
          }
        }
      } catch { /* ignore */ }
    }
  }
  return legacy;
}

function getCanonicalBase(platform) {
  const homeBase = process.env.LOCALAPPDATA
    || process.env.USERPROFILE
    || os.homedir();
  return platform === 'win32'
    ? path.join(homeBase, 'overmind', 'hermes')
    : path.join(homeBase, '.overmind', 'hermes');
}

function migrateOne(src, dst) {
  // src = legacy agent dir (e.g. <workspace>/.overmind/hermes/agent_foo)
  // dst = canonical agent dir (e.g. ~/.overmind/hermes/agent_foo)
  if (fs.existsSync(dst)) {
    log(`  SKIP: destination already exists: ${dst}`);
    return false;
  }
  if (dryRun) {
    log(`  DRY-RUN: would move ${src} -> ${dst}`);
    return true;
  }
  // Make parent if missing
  fs.mkdirSync(path.dirname(dst), { recursive: true });
  // Use rename for atomicity (works on same-filesystem; cross-fs would need copy+delete)
  try {
    fs.renameSync(src, dst);
    log(`  MOVED: ${src} -> ${dst}`);
    return true;
  } catch (e) {
    if (e.code === 'EXDEV') {
      // Cross-device: copy + delete
      log(`  CROSS-FS: copying ${src} -> ${dst}`);
      copyDirSync(src, dst);
      fs.rmSync(src, { recursive: true, force: true });
      return true;
    }
    throw e;
  }
}

function copyDirSync(src, dst) {
  fs.mkdirSync(dst, { recursive: true });
  for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
    const s = path.join(src, entry.name);
    const d = path.join(dst, entry.name);
    if (entry.isDirectory()) {
      copyDirSync(s, d);
    } else if (entry.isFile()) {
      fs.copyFileSync(s, d);
    }
  }
}

function main() {
  const workspaceDir = process.env.OVERMIND_WORKSPACE
    || process.cwd();
  const platform = process.platform;
  const canonicalBase = getCanonicalBase(platform);

  log(`workspace:  ${workspaceDir}`);
  log(`platform:   ${platform}`);
  log(`canonical:  ${canonicalBase}`);
  log(`mode:       ${dryRun ? 'DRY-RUN' : 'LIVE'}`);
  log('');

  const legacy = findLegacyBases(workspaceDir);
  if (legacy.length === 0) {
    log('No legacy .overmind directories found. Nothing to migrate.');
    return;
  }

  let moved = 0;
  for (const src of legacy) {
    const name = path.basename(src);
    const dst = path.join(canonicalBase, name);
    log(`Migrating ${name}:`);
    if (migrateOne(src, dst)) moved++;
  }

  log('');
  log(`Done. ${moved}/${legacy.length} agent directories migrated.`);
  if (dryRun) {
    log('Re-run without --dry-run to actually perform the migration.');
  }
}

main();
