import * as fs from "fs";
import * as path from "path";

import { execSync } from "child_process";

/**
 * Gets the current version tag from arguments, environment or git.
 */
function getVersionTag() {
  // 0. Check arguments (passed from husky hook or manual run)
  const argTag = process.argv.slice(2).find((arg) => arg.match(/^v?\d/));
  if (argTag) {
    return argTag;
  }

  // 1. Check CI environment variables
  if (
    process.env.GITHUB_REF_NAME &&
    process.env.GITHUB_REF_NAME.match(/^v?\d/)
  ) {
    return process.env.GITHUB_REF_NAME;
  }
  if (process.env.TAG && process.env.TAG.match(/^v?\d/)) {
    return process.env.TAG;
  }

  // 2. Try to get it from local git
  try {
    const gitTag = execSync("git describe --tags --abbrev=0", {
      encoding: "utf8",
    }).trim();
    if (gitTag && gitTag.match(/^v?\d/)) {
      return gitTag;
    }
  } catch (_e) {
    // Fallback or silence
  }

  return null;
}

const tag = getVersionTag();

if (!tag) {
  console.log(
    "ℹ️ No version tag found (starting with v). Skipping version sync.",
  );
  process.exit(0); // Exit gracefully if no tag is present
}

const version = tag.replace(/^v/, "");
console.log(`🚀 Syncing all packages to version: ${version}`);

const rootPkg = JSON.parse(fs.readFileSync("package.json", "utf-8"));
const packagesDir = "packages";
const appsDir = "apps";

function updatePkg(pkgPath: string) {
  if (!fs.existsSync(pkgPath)) return;
  const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
  pkg.version = version;

  // Also update workspace dependencies if they match our packages
  if (pkg.dependencies) {
    for (const dep in pkg.dependencies) {
      if (pkg.dependencies[dep].startsWith("workspace:")) {
        pkg.dependencies[dep] = "workspace:*"; // Keep workspace protocol
      }
    }
  }

  fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
  console.log(`✅ Updated ${pkg.name} to ${version}`);
}

/**
 * Updates the IMAGE_TAG in .env files.
 */
function updateEnv(envPath: string) {
  if (!fs.existsSync(envPath)) return;
  let content = fs.readFileSync(envPath, "utf-8");

  if (content.includes("IMAGE_TAG=")) {
    content = content.replace(/IMAGE_TAG=.*/g, `IMAGE_TAG=${tag}`);
  } else {
    // Proactively add it if missing
    if (content.includes("# Project")) {
      content = content.replace("# Project", `# Project\nIMAGE_TAG=${tag}`);
    } else {
      content = `IMAGE_TAG=${tag}\n${content}`;
    }
  }

  fs.writeFileSync(envPath, content);
  console.log(`✅ Updated IMAGE_TAG in ${envPath} to ${tag}`);
}

// Update root
rootPkg.version = version;
fs.writeFileSync("package.json", JSON.stringify(rootPkg, null, 2) + "\n");

// Update all packages
if (fs.existsSync(packagesDir)) {
  const packages = fs.readdirSync(packagesDir);
  for (const p of packages) {
    updatePkg(path.join(packagesDir, p, "package.json"));
  }
}

// Update all apps
if (fs.existsSync(appsDir)) {
  const apps = fs.readdirSync(appsDir);
  for (const a of apps) {
    updatePkg(path.join(appsDir, a, "package.json"));
  }
}

// Update .env files
updateEnv(".env");
updateEnv(".env.example");

console.log("✨ All versions synced!");
