const fs = require("node:fs");
const path = require("node:path");

const ROOT = path.resolve(__dirname, "..");
const LOGS = path.join(ROOT, "logs");
const SYSTEM = path.join(LOGS, "system");
const OLD_SYSTEM_SCOPES = ["00", "0000"];
const PROJECT_SCOPE_MAP = {
  "62e940d0": "AUXCR-1842",
  "62ea933d": "SNDBRD-2715",
  "62eb6afd": "NODWEB-4096",
  "62e9f73d": "ATELIR-6204"
};

function exists(filePath) {
  return fs.existsSync(filePath);
}

function ensureDir(dirPath) {
  fs.mkdirSync(dirPath, { recursive: true });
}

function listDirs(dirPath) {
  if (!exists(dirPath)) return [];
  return fs.readdirSync(dirPath, { withFileTypes: true }).filter(entry => entry.isDirectory()).map(entry => entry.name).sort();
}

function uniqueTarget(baseDir, name) {
  const parsed = path.parse(name);
  let target = path.join(baseDir, name);
  let index = 1;
  while (exists(target)) {
    target = path.join(baseDir, `${parsed.name}.retained-${index}${parsed.ext}`);
    index += 1;
  }
  return target;
}

function mergeDirContents(sourceDir, targetDir) {
  if (!exists(sourceDir)) return { moved: 0, retained: false };
  ensureDir(targetDir);
  let moved = 0;
  for (const name of fs.readdirSync(sourceDir)) {
    const from = path.join(sourceDir, name);
    const to = uniqueTarget(targetDir, name);
    fs.renameSync(from, to);
    moved += 1;
  }
  const remaining = fs.readdirSync(sourceDir);
  if (remaining.length === 0) fs.rmdirSync(sourceDir);
  return { moved, retained: remaining.length > 0 };
}

function retainProjectScope(oldSerial, newSerial) {
  const oldDir = path.join(LOGS, oldSerial);
  const newDir = path.join(LOGS, newSerial);
  if (!exists(oldDir)) return { oldSerial, newSerial, action: "missing_old_scope" };
  if (exists(newDir)) return { oldSerial, newSerial, action: "retained_old_scope_new_exists" };
  fs.renameSync(oldDir, newDir);
  return { oldSerial, newSerial, action: "renamed_old_scope" };
}

function audit() {
  return {
    logsRoot: LOGS,
    scopes: listDirs(LOGS),
    systemExists: exists(SYSTEM),
    oldSystemScopes: OLD_SYSTEM_SCOPES.filter(scope => exists(path.join(LOGS, scope))),
    projectScopes: Object.fromEntries(Object.entries(PROJECT_SCOPE_MAP).map(([oldSerial, newSerial]) => [oldSerial, {
      newSerial,
      oldExists: exists(path.join(LOGS, oldSerial)),
      newExists: exists(path.join(LOGS, newSerial))
    }]))
  };
}

function migrate() {
  ensureDir(LOGS);
  ensureDir(SYSTEM);
  const systemResults = OLD_SYSTEM_SCOPES.map(scope => {
    const source = path.join(LOGS, scope);
    const result = mergeDirContents(source, SYSTEM);
    return { scope, ...result };
  });
  const projectResults = Object.entries(PROJECT_SCOPE_MAP).map(([oldSerial, newSerial]) => retainProjectScope(oldSerial, newSerial));
  return { before: null, systemResults, projectResults, after: audit() };
}

const mode = process.argv[2] === "migrate" ? "migrate" : "audit";
console.log(JSON.stringify(mode === "migrate" ? migrate() : audit(), null, 2));
