/**
 * MigrateSwitchboardState — WP-14 one-shot layout migration.
 * Ensures VERSION.json and directory layout; does not rewrite FCoP TASK/REPORT.
 */

import { promises as fs } from "node:fs";
import { join } from "node:path";

import { SwitchboardPaths } from "../paths/SwitchboardPaths.js";
import {
  SWITCHBOARD_LAYOUT_VERSION,
  SwitchboardVersionStore,
} from "../store/SwitchboardVersionStore.js";
import { AtomicFile } from "../atomic/AtomicFile.js";

export interface MigrationGap {
  code: string;
  message: string;
}

export interface MigrationResult {
  schema: "codeflowmu.switchboard-migration/v1";
  migrated: boolean;
  fromVersion: number | null;
  toVersion: number;
  gaps: MigrationGap[];
  notes: string[];
  /** Existing TASK/REPORT are never rewritten. */
  fcopLedgerRewritten: false;
}

export interface MigrateOptions {
  persistDir: string;
  workerIds?: string[];
  dryRun?: boolean;
  now?: () => Date;
}

export async function migrateSwitchboardState(
  opts: MigrateOptions,
): Promise<MigrationResult> {
  const paths = new SwitchboardPaths({ persistDir: opts.persistDir });
  const versions = new SwitchboardVersionStore(paths);
  const existing = await versions.read();
  const gaps: MigrationGap[] = [];
  const notes: string[] = [];
  const fromVersion = existing?.layoutVersion ?? null;

  // Ensure canonical directories exist
  const dirs = [
    paths.root,
    paths.hostsDir(),
    paths.workersDir(),
    join(paths.root, "bindings"),
    join(paths.root, "mailboxes"),
    join(paths.root, "runs"),
    join(paths.root, "claims"),
    join(paths.root, "projections"),
    join(paths.root, "diagnostics"),
  ];

  if (!opts.dryRun) {
    for (const dir of dirs) {
      await fs.mkdir(dir, { recursive: true });
    }
  } else {
    notes.push("dryRun=true — directories not created");
  }

  let migrated = false;
  if (!existing) {
    if (!opts.dryRun) {
      await versions.write({
        notes: "wp-14-migrate-init",
        layoutVersion: SWITCHBOARD_LAYOUT_VERSION,
      });
    }
    migrated = true;
    notes.push("initialized VERSION.json");
  } else if (existing.layoutVersion < SWITCHBOARD_LAYOUT_VERSION) {
    gaps.push({
      code: "layout.upgrade_required",
      message: `found layoutVersion=${existing.layoutVersion}, target=${SWITCHBOARD_LAYOUT_VERSION}`,
    });
    if (!opts.dryRun) {
      await versions.write({
        notes: `wp-14-upgrade-from-${existing.layoutVersion}`,
        layoutVersion: SWITCHBOARD_LAYOUT_VERSION,
      });
      migrated = true;
    }
  } else if (existing.layoutVersion > SWITCHBOARD_LAYOUT_VERSION) {
    gaps.push({
      code: "layout.newer_than_runtime",
      message: `persist layoutVersion=${existing.layoutVersion} newer than runtime ${SWITCHBOARD_LAYOUT_VERSION}`,
    });
  } else {
    notes.push("already at target layoutVersion");
  }

  // Compatibility marker: old queue JSON may exist as derived only
  notes.push(
    "FCoP TASK/REPORT are never migrated or rewritten by this tool",
  );
  notes.push(
    "agent-task-queue.json if present must remain derived=true (WP-12)",
  );

  // Write migration receipt
  if (!opts.dryRun && migrated) {
    const receipt = join(paths.root, "diagnostics", "LAST-MIGRATION.json");
    await AtomicFile.writeJson(receipt, {
      schema: "codeflowmu.switchboard-migration/v1",
      at: (opts.now?.() ?? new Date()).toISOString(),
      fromVersion,
      toVersion: SWITCHBOARD_LAYOUT_VERSION,
      gaps,
      notes,
    });
  }

  return {
    schema: "codeflowmu.switchboard-migration/v1",
    migrated,
    fromVersion,
    toVersion: SWITCHBOARD_LAYOUT_VERSION,
    gaps,
    notes,
    fcopLedgerRewritten: false,
  };
}
