#!/usr/bin/env node
/**
 * @file One-off codemod: rewrites raw `emerald-*`/`red-*`/`amber-*` Tailwind
 * utilities across client/src to the shared `status-success`/`status-danger`/
 * `status-warning` CSS-variable tokens (see `src/index.css`), so every
 * badge/button/component that means "success"/"danger"/"warning" uses the
 * SAME shade per theme instead of each usage picking its own. The
 * categorical/decorative hue palette (violet, indigo, cyan, teal, sky, rose,
 * pink, orange, yellow, and `blue` — which doubles as both "info" and a
 * categorical role color in places like message bubbles) is deliberately
 * left alone: those distinguish between different *kinds* of thing, not a
 * status, and collapsing them would erase that distinction.
 * @author Nguyễn Ngọc Trí Vĩ <vinnt@smartgift.vn>
 */
import { readdirSync, readFileSync, writeFileSync, statSync } from "node:fs";
import { join } from "node:path";
import { fileURLToPath } from "node:url";

const COLOR_TO_STATUS = {
  emerald: "status-success",
  red: "status-danger",
  amber: "status-warning",
};
const PROPS = ["text", "bg", "border", "ring", "from", "to", "via", "fill", "placeholder"];

function rewrite(text) {
  let out = text;
  for (const prop of PROPS) {
    for (const [color, token] of Object.entries(COLOR_TO_STATUS)) {
      // Shade number is dropped entirely — the token carries its own
      // per-theme value, so `emerald-400`, `emerald-500`, `emerald-600` all
      // collapse onto the one `status-success` (that collapse IS the fix:
      // no more per-usage shade picking). Opacity suffix (`/10`, `/60`) is
      // preserved verbatim.
      const re = new RegExp(`\\b${prop}-${color}-[0-9]+(\\/\\[[0-9.]+\\]|\\/[0-9]+)?`, "g");
      out = out.replace(re, (_m, opacity) => `${prop}-${token}${opacity || ""}`);
    }
  }
  return out;
}

function walk(dir, files = []) {
  for (const entry of readdirSync(dir)) {
    const full = join(dir, entry);
    const st = statSync(full);
    if (st.isDirectory()) {
      if (entry === "node_modules") continue;
      walk(full, files);
    } else if (entry.endsWith(".tsx")) {
      files.push(full);
    }
  }
  return files;
}

const scriptDir = fileURLToPath(new URL(".", import.meta.url));
const root = join(scriptDir, "..", "client", "src");
const files = walk(root);
let changed = 0;
for (const file of files) {
  const before = readFileSync(file, "utf8");
  const after = rewrite(before);
  if (after !== before) {
    writeFileSync(file, after);
    changed++;
  }
}
console.log(`rewrote ${changed} file(s)`);
