#!/usr/bin/env node
import { execSync } from "node:child_process";
import { readFileSync, writeFileSync } from "node:fs";
import { fileURLToPath } from "node:url";
import { dirname, resolve } from "node:path";

const __dirname = dirname(fileURLToPath(import.meta.url));
const versionPath = resolve(__dirname, "..", "version.json");

function git(args) {
  return execSync(`git ${args}`, { encoding: "utf8" }).trim();
}

let commit = "unknown";
let date = new Date().toISOString().slice(0, 10).replace(/-/g, "");
try {
  commit = git("log -1 --format=%h");
  date = git("log -1 --format=%cd --date=format:%Y%m%d");
} catch (err) {
  console.warn(`[update-version] git unavailable, using fallback: ${err.message}`);
}

const build = `${date}.${commit}`;
const current = JSON.parse(readFileSync(versionPath, "utf8"));

// #597: derive the stable base from the existing `version` field on
// first run so older repos migrate cleanly. e.g. "0.1.0-dev.5" -> base
// "0.1.0-dev", count 5. A bare "0.1.0-dev" (no trailing .N) just stays
// the base and starts counting from the current deployCount (or 0).
const TRAILING_COUNTER = /\.(\d+)$/;
function deriveBase(versionStr) {
  if (typeof versionStr !== "string" || versionStr.length === 0) {
    return "0.1.0-dev";
  }
  const m = versionStr.match(TRAILING_COUNTER);
  return m ? versionStr.slice(0, -m[0].length) : versionStr;
}

const baseVersion =
  typeof current.baseVersion === "string" && current.baseVersion.length > 0
    ? current.baseVersion
    : deriveBase(current.version);

let deployCount = Number.isInteger(current.deployCount)
  ? current.deployCount
  : (() => {
      // Seed from the trailing counter on the existing version string
      // so first migration doesn't reset progress to 0 if the user had
      // already been numbering manually (e.g. "0.1.0-dev.12").
      const m =
        typeof current.version === "string"
          ? current.version.match(TRAILING_COUNTER)
          : null;
      return m ? parseInt(m[1], 10) : 0;
    })();

// Always bump on every build/redeploy, even when the commit hash hasn't
// changed. The user wants the version label to reflect every deploy so
// they can confirm a redeploy actually rolled out new code on the Mac.
deployCount += 1;
const version = `${baseVersion}.${deployCount}`;
const next = { baseVersion, version, build, deployCount };
writeFileSync(versionPath, JSON.stringify(next, null, 2) + "\n");
console.log(
  `[update-version] ${current.build} -> ${build} | ${current.version ?? "<none>"} -> ${version}`,
);
