const { getUpdateStatus } = require("./update-index");
const { applyCoreUpdate, deployCoreBranch } = require("./repo-update");
const {
  normalizeRepositoryTarget,
  readUpdateState,
  resolveSourceBranch
} = require("./update-repository");

let restartHandler = null;

function normalizeUpdateSource(branch) {
  const requested = String(branch || "main").trim();
  if (requested === "main" || requested === "stable") return "stable";
  if (requested === "experimental") return "experimental";
  return requested || "stable";
}

function checkForUpdates(remote, branch) {
  const target = normalizeRepositoryTarget(remote);
  const source = normalizeUpdateSource(branch);
  const status = getUpdateStatus({ remote: target, source });
  return Boolean(status.core?.update_available);
}

async function pullUpdates(remote, branch) {
  const target = normalizeRepositoryTarget(remote);
  const source = normalizeUpdateSource(branch);
  const result = await applyCoreUpdate({ remote: target, source });
  return `Applied core update from ${result.target.source_branch}.`;
}

function resolveUpdateBranch(remote, branch) {
  return resolveSourceBranch(normalizeRepositoryTarget(remote), normalizeUpdateSource(branch));
}

function pendingDeploymentBranch(state, configuredBranch, localVersion) {
  if (String(configuredBranch || "") !== "experimental") return null;
  const targetBranch = String(state.branch || "");
  const confirmedCoreUpdate =
    state.last_update_status === "complete" &&
    state.last_target_kind === "core" &&
    state.last_target_version === localVersion &&
    Boolean(state.last_snapshot_id);
  if (
    state.deployed_branch === targetBranch ||
    !confirmedCoreUpdate ||
    !targetBranch.startsWith("experimental-")
  ) return null;
  return targetBranch;
}

async function completePendingBranchDeployment(remote, configuredBranch) {
  const state = readUpdateState();
  const localVersion = require("../../package.json").version;
  const targetBranch = pendingDeploymentBranch(state, configuredBranch, localVersion);
  if (!targetBranch) return null;
  return deployCoreBranch({ branch: targetBranch, remote });
}

function registerRestartHandler(handler) {
  restartHandler = typeof handler === "function" ? handler : null;
  return () => {
    if (restartHandler === handler) restartHandler = null;
  };
}

function requestRestart(options = {}) {
  const delayMs = Math.max(0, Number(options.delayMs ?? 500));
  setTimeout(() => {
    if (!restartHandler) {
      process.exit(10);
      return;
    }
    Promise.resolve(restartHandler(10)).catch((error) => {
      console.error("Graceful restart failed; forcing wrapper restart.", error);
      process.exit(10);
    });
  }, delayMs);
}

module.exports = {
  checkForUpdates,
  completePendingBranchDeployment,
  pullUpdates,
  normalizeRepositoryTarget,
  pendingDeploymentBranch,
  resolveUpdateBranch,
  registerRestartHandler,
  requestRestart
};
