// scripts/optimize-models.mjs
// Nén .glb: backup bản gốc rồi tối ưu (meshopt + nén texture webp).
// Chạy: node scripts/optimize-models.mjs  (an toàn chạy lại — luôn nén từ backup gốc)
import { promises as fs } from "node:fs";
import path from "node:path";
import { execFile } from "node:child_process";
import { promisify } from "node:util";

const run = promisify(execFile);
const ROOT = process.cwd();
const MODEL_DIR = path.join(ROOT, "public/antiquity");
const BACKUP_DIR = path.join(ROOT, "model-originals");
const fmt = (b) => (b / 1024 / 1024).toFixed(2) + "MB";
const exists = (p) => fs.access(p).then(() => true).catch(() => false);

async function optimizeModel(file) {
  const dest = path.join(MODEL_DIR, file);
  const backup = path.join(BACKUP_DIR, file);
  await fs.mkdir(BACKUP_DIR, { recursive: true });
  if (!(await exists(backup))) {
    await fs.copyFile(dest, backup);
  }
  const before = (await fs.stat(dest)).size;
  // Luôn tối ưu TỪ backup gốc; ghi đè ra dest.
  const isWin = process.platform === "win32";
  const bin = path.join(ROOT, "node_modules/.bin", isWin ? "gltf-transform.cmd" : "gltf-transform");
  const q = (s) => (isWin ? `"${s}"` : s);
  await run(
    q(bin),
    [
      "optimize",
      q(backup),
      q(dest),
      "--compress", "meshopt",
      "--texture-compress", "webp",
    ],
    // Trên Windows phải chạy .cmd qua shell (Node >=18 ném EINVAL nếu spawn .cmd trực tiếp).
    { shell: isWin }
  );
  const after = (await fs.stat(dest)).size;
  console.log(`${file}: ${fmt(before)} -> ${fmt(after)} (-${Math.round((1 - after / before) * 100)}%)`);
}

try {
  const files = (await fs.readdir(MODEL_DIR)).filter((f) => /\.glb$/i.test(f)).sort();
  for (const f of files) {
    await optimizeModel(f);
  }
  console.log("Done.");
} catch (err) {
  console.error("optimize-models failed:", err);
  process.exit(1);
}
