(function initFivaFileUtils(global) {
  "use strict";

  const ACCEPTED_TYPES = Object.freeze([
    "application/pdf",
    "image/png",
    "image/jpeg"
  ]);

  function isAccepted(file) {
    if (!file) return false;
    const name = String(file.name || "").toLowerCase();
    return ACCEPTED_TYPES.includes(file.type)
      || name.endsWith(".pdf")
      || name.endsWith(".png")
      || name.endsWith(".jpg")
      || name.endsWith(".jpeg");
  }

  function isPdf(file) {
    return file?.type === "application/pdf" || /\.pdf$/i.test(file?.name || "");
  }

  function isImage(file) {
    return /^image\/(png|jpeg)$/i.test(file?.type || "") || /\.(png|jpe?g)$/i.test(file?.name || "");
  }

  function readAsArrayBuffer(file) {
    return new Promise((resolve, reject) => {
      const reader = new FileReader();
      reader.onload = () => resolve(reader.result);
      reader.onerror = () => reject(reader.error || new Error("Could not read file."));
      reader.readAsArrayBuffer(file);
    });
  }

  function readAsDataUrl(file) {
    return new Promise((resolve, reject) => {
      const reader = new FileReader();
      reader.onload = () => resolve(reader.result);
      reader.onerror = () => reject(reader.error || new Error("Could not read file."));
      reader.readAsDataURL(file);
    });
  }

  function downloadJson(fileName, data) {
    const blob = new Blob([JSON.stringify(data, null, 2)], { type: "application/json" });
    const url = URL.createObjectURL(blob);
    const anchor = document.createElement("a");
    anchor.href = url;
    anchor.download = fileName;
    anchor.click();
    setTimeout(() => URL.revokeObjectURL(url), 1000);
  }

  const FileUtils = Object.freeze({
    ACCEPTED_TYPES,
    downloadJson,
    isAccepted,
    isImage,
    isPdf,
    readAsArrayBuffer,
    readAsDataUrl
  });

  global.FIVA = Object.assign(global.FIVA || {}, { FileUtils });
})(typeof globalThis !== "undefined" ? globalThis : this);
