#!/usr/bin/env bun

import { writeFileSync } from "fs";
import { join } from "path";
import ROOT from "./ROOT.js";

// 忽略 SSL 证书验证错误
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";

const URL = "https://cdn.jsdelivr.net/npm/mime-db/db.json",
  toRustConst = (mime) => {
    let name = mime.toUpperCase().replace(/[^A-Z0-9]/g, "_");
    if (/^[0-9]/.test(name)) {
      name = "_" + name;
    }
    name = name.replace(/_+/g, "_");
    name = name.replace(/^_+|_+$/g, "");
    return name;
  },
  main = async () => {
    console.log("通过 fetch 获取 mime-db...");
    let response;
    try {
      response = await fetch(URL);
      if (!response.ok) {
        throw new Error("HTTP 错误: " + response.statusText);
      }
    } catch (err) {
      throw new Error("获取失败: " + err.message);
    }
    const db = await response.json();
    if (db["application/json"]) {
      db["application/json"].extensions = [];
    }
    db["text/json"] = {
      source: "iana",
      compressible: true,
      extensions: ["json"],
    };

    const mime_to_const = new Map(),
      seen_consts = new Set(),
      script_name = "gen.js";

    // First, generate unique Rust const names for each mime
    for (const mime of Object.keys(db)) {
      const const_name = toRustConst(mime);
      let name = const_name,
        i = 1;
      while (seen_consts.has(name)) {
        name = const_name + "_" + i;
        i += 1;
      }
      seen_consts.add(name);
      mime_to_const.set(mime, name);
    }

    // Generate src/mime.rs
    let mime_rs = "// This file is generated by js/" + script_name + ". Do not edit.\n\n";
    for (const [mime, const_name] of mime_to_const.entries()) {
      mime_rs += "pub const " + const_name + ': &str = "' + mime + '";\n';
    }

    /*
  Generate src/ext_mime.rs
  Map extension -> mime
  */
    const ext_to_mime = new Map();
    for (const [mime, info] of Object.entries(db)) {
      if (info.extensions) {
        for (const ext of info.extensions) {
          const existing_mime = ext_to_mime.get(ext);
          if (!existing_mime) {
            ext_to_mime.set(ext, mime);
          } else {
            // Priority logic: iana > compressible > shorter mime length
            const existing_info = db[existing_mime],
              new_score = (info.source === "iana" ? 2 : 0) + (info.compressible ? 1 : 0),
              old_score =
                (existing_info.source === "iana" ? 2 : 0) + (existing_info.compressible ? 1 : 0);
            if (new_score > old_score) {
              ext_to_mime.set(ext, mime);
            } else if (new_score === old_score) {
              // Keep the one with shorter length or alphabetical if same length
              if (mime.length < existing_mime.length) {
                ext_to_mime.set(ext, mime);
              }
            }
          }
        }
      }
    }

    // Sort extensions to keep output deterministic
    const sorted_exts = Array.from(ext_to_mime.keys()).sort();

    let ext_mime_rs =
      "// This file is generated by js/" +
      script_name +
      ". Do not edit.\n\nuse crate::mime;\n\npub static EXT_MIME: phf::Map<&'static str, &'static str> = phf::phf_map! {\n";
    for (const ext of sorted_exts) {
      const mime = ext_to_mime.get(ext),
        const_name = mime_to_const.get(mime);
      ext_mime_rs += '  "' + ext + '" => mime::' + const_name + ",\n";
    }
    ext_mime_rs += "};\n";

    writeFileSync(join(ROOT, "src/mime.rs"), mime_rs);
    writeFileSync(join(ROOT, "src/ext_mime.rs"), ext_mime_rs);
    console.log("成功生成 src/mime.rs 与 src/ext_mime.rs。");
  };

try {
  await main();
} catch (err) {
  process.stderr.write(err.message + "\n");
  process.exit(1);
}
