const fs = require("fs");
const path = require("path");
const crypto = require("crypto");
const { writeJsonAtomicSync } = require("./safe-files");

const repoRoot = path.join(__dirname, "..", "..");
const recoveryDir = path.join(repoRoot, "data", "recovery");
const markerPath = path.join(recoveryDir, "update-marker.json");
const safeModeFlagPath = path.join(recoveryDir, "safe-mode.flag");

function ensureRecoveryDir() {
  fs.mkdirSync(recoveryDir, { recursive: true });
}

function readRecoveryMarker() {
  try {
    if (!fs.existsSync(markerPath)) return null;
    const marker = JSON.parse(fs.readFileSync(markerPath, "utf8"));
    return marker && typeof marker === "object" ? marker : null;
  } catch {
    return {
      id: "unreadable",
      status: "failed",
      error: "Recovery marker could not be parsed.",
      marker_path: markerPath
    };
  }
}

function writeRecoveryMarker(marker) {
  ensureRecoveryDir();
  const next = {
    id: marker.id || crypto.randomUUID(),
    status: marker.status || "pending",
    updated_at: new Date().toISOString(),
    ...marker
  };
  writeJsonAtomicSync(markerPath, next);
  return next;
}

function createRecoveryMarker(details) {
  return writeRecoveryMarker({
    id: crypto.randomUUID(),
    status: "pending",
    created_at: new Date().toISOString(),
    ...details
  });
}

function updateRecoveryMarker(values) {
  const current = readRecoveryMarker() || {};
  return writeRecoveryMarker({ ...current, ...values });
}

function markRecoveryMarkerFailed(error) {
  return updateRecoveryMarker({
    status: "failed",
    error: error?.message || String(error || "Update failed.")
  });
}

function markRecoveryMarkerComplete(values = {}) {
  return updateRecoveryMarker({
    ...values,
    status: "completed",
    completed_at: new Date().toISOString()
  });
}

function clearRecoveryMarker() {
  try {
    fs.rmSync(markerPath, { force: true });
  } catch {
    // ignore cleanup failures
  }
}

function markStartupVerification() {
  const marker = readRecoveryMarker();
  if (!marker) return null;
  if (marker.status === "completed") {
    clearRecoveryMarker();
    return { ...marker, cleared: true };
  }
  if (["pending", "applying", "verifying"].includes(marker.status)) {
    return writeRecoveryMarker({
      ...marker,
      status: "stale",
      stale_at: new Date().toISOString(),
      error: marker.error || "Previous update did not complete startup verification."
    });
  }
  return marker;
}

function isSafeModeRequested(argv = process.argv, env = process.env) {
  return env.LUMI_SAFE_MODE === "1" ||
    env.SAFE_MODE === "1" ||
    argv.includes("--safe-mode") ||
    fs.existsSync(safeModeFlagPath);
}

function safeModeStatus() {
  const marker = readRecoveryMarker();
  const requested = isSafeModeRequested();
  const incomplete = marker && ["pending", "applying", "verifying", "failed", "stale"].includes(marker.status);
  return {
    requested,
    active: process.env.SAFE_MODE === "1" || process.env.LUMI_SAFE_MODE === "1",
    marker,
    has_incomplete_marker: Boolean(incomplete),
    safe_mode_flag: fs.existsSync(safeModeFlagPath),
    marker_path: markerPath,
    flag_path: safeModeFlagPath
  };
}

module.exports = {
  recoveryDir,
  markerPath,
  safeModeFlagPath,
  readRecoveryMarker,
  writeRecoveryMarker,
  createRecoveryMarker,
  updateRecoveryMarker,
  markRecoveryMarkerFailed,
  markRecoveryMarkerComplete,
  clearRecoveryMarker,
  markStartupVerification,
  isSafeModeRequested,
  safeModeStatus
};
