import { copyFile, mkdir, readdir, readFile, writeFile } from "node:fs/promises";
import path from "node:path";

const sourceRoot = process.argv[2];
const targetRoot = process.env.UPLOAD_DIR || process.argv[3];
if (!sourceRoot || !targetRoot) {
  throw new Error(
    "用法：UPLOAD_DIR=/data/koc/uploads npm run storage:import -- /path/to/r2-export",
  );
}

const contentTypes = {
  ".avif": "image/avif",
  ".gif": "image/gif",
  ".jpeg": "image/jpeg",
  ".jpg": "image/jpeg",
  ".png": "image/png",
  ".webp": "image/webp",
};

let copied = 0;
async function walk(directory) {
  const entries = await readdir(directory, { withFileTypes: true });
  for (const entry of entries) {
    const absolute = path.join(directory, entry.name);
    if (entry.isDirectory()) {
      await walk(absolute);
      continue;
    }
    if (entry.name.endsWith(".metadata.json")) continue;
    const relative = path.relative(sourceRoot, absolute);
    if (relative.startsWith("..") || path.isAbsolute(relative)) {
      throw new Error("导入目录越界");
    }
    const destination = path.join(targetRoot, relative);
    await mkdir(path.dirname(destination), { recursive: true });
    await copyFile(absolute, destination);
    const sourceMetadata = `${absolute}.metadata.json`;
    const metadataDestination = `${destination}.metadata.json`;
    let metadata;
    try {
      metadata = JSON.parse(await readFile(sourceMetadata, "utf8"));
    } catch {
      metadata = {
        contentType:
          contentTypes[path.extname(entry.name).toLowerCase()] ||
          "application/octet-stream",
        customMetadata: { source: "r2-export" },
        uploadedAt: new Date().toISOString(),
      };
    }
    await writeFile(metadataDestination, JSON.stringify(metadata), "utf8");
    copied += 1;
  }
}

await mkdir(targetRoot, { recursive: true });
await walk(sourceRoot);
console.info(`imported objects: ${copied}`);
