import fs from "node:fs/promises";
import path from "node:path";
import sharp from "sharp";

const ROOT = process.cwd();
const TARGET_DIRS = ["public", "images"];
const SKIP_DIRS = new Set(["node_modules", ".next", "out", ".git"]);
const EXTENSIONS = new Set([".jpg", ".jpeg", ".png"]);

async function exists(p) {
  try {
    await fs.access(p);
    return true;
  } catch {
    return false;
  }
}

async function walk(dir, files = []) {
  const entries = await fs.readdir(dir, { withFileTypes: true });
  for (const entry of entries) {
    const fullPath = path.join(dir, entry.name);
    if (entry.isDirectory()) {
      if (SKIP_DIRS.has(entry.name)) continue;
      await walk(fullPath, files);
    } else if (entry.isFile()) {
      const ext = path.extname(entry.name).toLowerCase();
      if (EXTENSIONS.has(ext)) {
        files.push(fullPath);
      }
    }
  }
  return files;
}

async function optimizeImage(filePath) {
  const ext = path.extname(filePath).toLowerCase();
  const input = sharp(filePath);
  const tempPath = `${filePath}.tmp`;

  if (ext === ".png") {
    await input.png({ compressionLevel: 9, adaptiveFiltering: true }).toFile(tempPath);
  } else {
    await input.jpeg({ quality: 82, mozjpeg: true }).toFile(tempPath);
  }

  const [origStat, tempStat] = await Promise.all([
    fs.stat(filePath),
    fs.stat(tempPath),
  ]);

  if (tempStat.size <= origStat.size) {
    await fs.rename(tempPath, filePath);
  } else {
    await fs.unlink(tempPath);
  }
}

async function main() {
  const targets = [];
  for (const dir of TARGET_DIRS) {
    const full = path.join(ROOT, dir);
    if (await exists(full)) targets.push(full);
  }

  if (targets.length === 0) {
    console.log("No image directories found (public/, images/).");
    return;
  }

  const files = [];
  for (const dir of targets) {
    await walk(dir, files);
  }

  if (files.length === 0) {
    console.log("No .jpg/.jpeg/.png files found.");
    return;
  }

  console.log(`Optimizing ${files.length} images...`);
  for (const file of files) {
    try {
      await optimizeImage(file);
    } catch (err) {
      console.warn(`Skipping ${file}: ${err?.message ?? err}`);
    }
  }
}

main().catch((err) => {
  console.error(err);
  process.exit(1);
});