/**
 * Minimal extension ↔ MIME mapping + `accept` matching. Zero-dep: just a table
 * big enough for the common upload types (images, docs, media, archives).
 */

const BY_EXT: Record<string, string> = {
  // images
  png: "image/png",
  jpg: "image/jpeg",
  jpeg: "image/jpeg",
  gif: "image/gif",
  webp: "image/webp",
  avif: "image/avif",
  svg: "image/svg+xml",
  ico: "image/x-icon",
  bmp: "image/bmp",
  // documents
  pdf: "application/pdf",
  txt: "text/plain",
  html: "text/html",
  htm: "text/html",
  csv: "text/csv",
  json: "application/json",
  xml: "application/xml",
  doc: "application/msword",
  docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
  xls: "application/vnd.ms-excel",
  xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
  ppt: "application/vnd.ms-powerpoint",
  pptx: "application/vnd.openxmlformats-officedocument.presentationml.presentation",
  // media
  mp3: "audio/mpeg",
  wav: "audio/wav",
  ogg: "audio/ogg",
  mp4: "video/mp4",
  webm: "video/webm",
  mov: "video/quicktime",
  // archives / misc
  zip: "application/zip",
  gz: "application/gzip",
  tar: "application/x-tar",
};

/** Lowercased extension WITHOUT the dot (e.g. "png"), or "" if none. */
export function extOf(name: string): string {
  const clean = name.split(/[?#]/)[0] ?? "";
  const dot = clean.lastIndexOf(".");
  return dot >= 0 ? clean.slice(dot + 1).toLowerCase() : "";
}

/** MIME type for a filename/key by its extension, or a safe default. */
export function contentTypeOf(name: string, fallback = "application/octet-stream"): string {
  return BY_EXT[extOf(name)] ?? fallback;
}

/** The conventional extension for a MIME type, or "" (used to name S3 keys). */
export function extForType(type: string): string {
  const t = type.split(";")[0]!.trim().toLowerCase();
  for (const [ext, mime] of Object.entries(BY_EXT)) if (mime === t) return ext;
  return "";
}

/**
 * Does `file` (its MIME `type` + `name`) satisfy an `accept` list? Each accept
 * entry is a MIME type (`"image/png"`), a wildcard MIME (`"image/*"`), or a
 * dotted extension (`".pdf"`). An empty/omitted list accepts everything.
 */
export function accepts(
  accept: string[] | undefined,
  file: { type: string; name: string },
): boolean {
  if (!accept || accept.length === 0) return true;
  const type = (file.type || contentTypeOf(file.name)).toLowerCase();
  const ext = "." + extOf(file.name);
  return accept.some((raw) => {
    const rule = raw.trim().toLowerCase();
    if (rule.startsWith(".")) return rule === ext;
    if (rule.endsWith("/*")) return type.startsWith(rule.slice(0, -1)); // "image/" prefix
    return rule === type;
  });
}
