/*
Client side JavaScript code for TYPO3 v12 and newer.
 */
import AjaxRequest from "@typo3/core/ajax/ajax-request.js";
import Modal from "@typo3/backend/modal.js";
import Severity from "@typo3/backend/severity.js";
import { MessageUtility } from "@typo3/backend/utility/message-utility.js";
import NProgress from "nprogress";

function init() {
  document.getElementById("snaatch-btn").addEventListener("click", (e) => {
    e.preventDefault();

    document.getElementById("snaatch-folder-modal-bg").style.display = "block";
    document.getElementById("snaatch-folder-container").classList.add("loading");

    /** @type HTMLIFrameElement*/
    const iframe = document.getElementById("snaatch-iframe");
    iframe.src = iframe.dataset.src;
    iframe.onload = () => {
      document.getElementById("snaatch-folder-container").classList.remove("loading");
      document.getElementById("snaatch-folder-modal-bg").style.display = "none";
      document.getElementById("snaatch-iframe-container").style.display = "block";
    };
  });

  document.getElementById("snaatch-close-btn").addEventListener("click", () => {
    document.getElementById("snaatch-iframe-container").style.display = "none";
    hideProgressIndicator();
  });

  document.getElementById("snaatch-folder-modal-close-btn").addEventListener("click", () => {
    document.getElementById("snaatch-folder-modal-bg").style.display = "none";
    hideProgressIndicator();
  });
}

if (document.readyState === "complete") {
  init();
} else {
  document.addEventListener("readystatechange", (e) => {
    if (e.target.readyState === "complete") {
      init();
    }
  });
}

console.log("TYPO3-PLUGIN[parent]: Listener initialized", {
  href: window.location.href,
  origin: window.location.origin,
});

const allowedMessageOrigins = [
  "https://app.vaulo.com",
];
const SINGLE_FILE_MESSAGE_BATCH_MS = 250;
let pendingSingleFileSelections = [];
let pendingSingleFileSelectionTimer = null;

/**
 * @param {MessageEvent} messageEvent
 * @returns {object | null}
 */
function getMessagePayload(messageEvent) {
  if (typeof messageEvent?.data === "string") {
    try {
      return JSON.parse(messageEvent.data);
    } catch (_error) {
      return null;
    }
  }
  return messageEvent?.data ?? null;
}

function flushPendingSingleFileSelections() {
  if (!pendingSingleFileSelections.length) {
    return;
  }

  const filesToProcess = [...pendingSingleFileSelections];
  pendingSingleFileSelections = [];
  pendingSingleFileSelectionTimer = null;

  console.log("TYPO3-PLUGIN[parent]: Processing batched file-selected messages", {
    count: filesToProcess.length,
  });
  selectFolderAndStartDownload(filesToProcess);
}

window.addEventListener("message", (messageEvent) => {
  const payload = getMessagePayload(messageEvent);

  console.log("TYPO3-PLUGIN[parent]: Message received", {
    origin: messageEvent.origin,
    subject: payload?.subject,
    data: payload,
  });

  const isAllowedOrigin = allowedMessageOrigins.includes(messageEvent.origin);

  if (!isAllowedOrigin || !payload?.subject) {
    console.warn("TYPO3-PLUGIN[parent]: Message ignored", {
      origin: messageEvent.origin,
      allowedOrigins: allowedMessageOrigins,
      isAllowedOrigin,
      hasSubject: Boolean(payload?.subject),
      data: payload,
    });
    return;
  }
  
  switch (payload.subject) {
    case "file-selected":
      console.log("TYPO3-PLUGIN: messageEventListener: ", payload);
      pendingSingleFileSelections.push(payload);
      if (pendingSingleFileSelectionTimer) {
        clearTimeout(pendingSingleFileSelectionTimer);
      }
      pendingSingleFileSelectionTimer = setTimeout(
        flushPendingSingleFileSelections,
        SINGLE_FILE_MESSAGE_BATCH_MS
      );
      break;
    case "files-selected":
      console.log("TYPO3-PLUGIN: messageEventListener: ", payload);
      if (pendingSingleFileSelectionTimer) {
        clearTimeout(pendingSingleFileSelectionTimer);
        pendingSingleFileSelectionTimer = null;
      }
      pendingSingleFileSelections = [];
      selectFolderAndStartDownload(payload.files);
      break;
  }
});

//region Folder Selector
/**
 * @typedef {Object} Folder
 * @property {string} name
 * @property {Folder[] | undefined} children
 */

/**
 * @typedef {Object.<string, string>} PathList
 */

let isDownloadInProgress = false;
let isSelectionFlowInProgress = false;

const folderSvg = `<svg class="folder-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 25.705 22.972">
<path id="Pfad_190" data-name="Pfad 190" d="M118.586,160.336H106.62a2.191,2.191,0,0,0-2.131,1.72l-.005.02-2.891,10.419a3.864,3.864,0,0,1-1.186,2.007h15.91a2.207,2.207,0,0,0,2.149-1.8l0-.018L120.737,163a2.271,2.271,0,0,0-.461-1.847,2.173,2.173,0,0,0-1.689-.813Zm0,0" transform="translate(-95.071 -151.53)" fill="#dfbc5f"/>
<path id="Pfad_191" data-name="Pfad 191" d="M15.193,1.541a2.607,2.607,0,0,1,2.546,2.168h.153a2.562,2.562,0,0,1,2.5,2.122h.441V3.009a2.381,2.381,0,0,0-2.353-2.4h-4.6a3.082,3.082,0,0,1-2.048-.782l-1.467-1.3a2.165,2.165,0,0,0-1.438-.549H2.353A2.381,2.381,0,0,0,0,.374V18.038a2.92,2.92,0,0,0,1.389,2.5V4.724A3.156,3.156,0,0,1,4.508,1.541Zm0,0" transform="translate(0 2.028)" fill="#dfbc5f"/>
<path id="Pfad_192" data-name="Pfad 192" d="M94.249,135.238l2.891-10.419a3.122,3.122,0,0,1,3.033-2.439h7.89a1.622,1.622,0,0,0-1.546-1.174H95.787a2.215,2.215,0,0,0-2.19,2.235v13.085a2.923,2.923,0,0,0,.646-1.268Zm0,0" transform="translate(-88.624 -114.523)" fill="#dfbc5f"/>
<path id="Pfad_193" data-name="Pfad 193" d="M58.1,82.462a1.667,1.667,0,0,0-1.593-1.219H45.823a2.215,2.215,0,0,0-2.19,2.235V99.647a2.8,2.8,0,0,0,1.725-.215V85.645a3.155,3.155,0,0,1,3.119-3.184Zm0,0" transform="translate(-41.314 -76.726)" fill="#dfbc5f"/>
</svg>
`;

const chevronRightSvg = `<svg class="chevron-right-icon" viewBox="0 0 32 32" fill="none" aria-hidden="true" xmlns="http://www.w3.org/2000/svg">
<path d="M17.947 16.095C17.999 16.043 17.999 15.9585 17.947 15.9065L11.6295 9.58899C11.3691 9.32864 11.3691 8.90653 11.6295 8.64618L13.2323 7.04341C13.4926 6.78306 13.9147 6.78306 14.1751 7.04341L21.0289 13.8973C21.0392 13.9064 21.0493 13.9158 21.0591 13.9257L22.6619 15.5285C22.9223 15.7888 22.9223 16.2109 22.6619 16.4713L14.1766 24.9565C13.9163 25.2169 13.4942 25.2169 13.2338 24.9565L11.631 23.3538C11.3707 23.0934 11.3707 22.6713 11.631 22.411L17.947 16.095Z" fill="currentColor"/>
</svg>`;

const chevronDownSvg = `<svg class="chevron-down-icon" viewBox="0 0 32 32" fill="none" aria-hidden="true" xmlns="http://www.w3.org/2000/svg">
<path d="M15.905 17.4809C15.9571 17.533 16.0415 17.533 16.0936 17.4809L22.4111 11.1635C22.6714 10.9031 23.0935 10.9031 23.3539 11.1635L24.9567 12.7662C25.217 13.0266 25.217 13.4487 24.9567 13.709L18.1028 20.5629C18.0937 20.5732 18.0842 20.5833 18.0744 20.5931L16.4716 22.1959C16.2113 22.4562 15.7892 22.4562 15.5288 22.1959L7.04353 13.7106C6.78318 13.4503 6.78318 13.0281 7.04353 12.7678L8.6463 11.165C8.90665 10.9047 9.32876 10.9047 9.58911 11.165L15.905 17.4809Z" fill="currentColor"/>
</svg>`;

const newSvg = `<svg class="new-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
      <g id="new" transform="translate(-7.875 -7.875)">
        <path id="Pfad_2937" data-name="Pfad 2937" d="M15.875,7.875a.889.889,0,0,1,.889.889v7.111a.889.889,0,0,1-.889.889H8.764a.889.889,0,1,1,0-1.778h6.222V8.764A.889.889,0,0,1,15.875,7.875Z" transform="translate(0 0)" fill="#002032" fill-rule="evenodd"/>
        <path id="Pfad_2938" data-name="Pfad 2938" d="M16.875,17.764a.889.889,0,0,1,.889-.889h7.111a.889.889,0,0,1,0,1.778H18.653v6.222a.889.889,0,0,1-1.778,0Z" transform="translate(-1.889 -1.889)" fill="#002032" fill-rule="evenodd"/>
      </g>
    </svg>`;

/**
 * @param {MouseEvent} ev
 */
function folderHandleFolderPress(ev) {
  if (isDownloadInProgress) {
    return;
  }
  
  const folderSelectBtn = document.getElementById("snaatch-folder-select-btn");
  const folderSelectBtnPath = document.getElementById("snaatch-folder-select-btn-path");
  
  if (!folderSelectBtn || !folderSelectBtnPath) {
    console.warn("Folder selection elements not found");
    return;
  }
  
  const allFolderItems = document.getElementsByClassName("snaatch-folder-item");
  for (let item of allFolderItems) {
    item.dataset.selected = "false";
  }
  
  const folderItem = ev.target.closest('.snaatch-folder-item');
  if (!folderItem) {
    console.warn("Could not find folder item element");
    return;
  }
  
  folderItem.dataset.selected = "true";
  
  const selectedPath = folderItem.dataset.path;
  if (selectedPath) {
    folderSelectBtnPath.innerText = selectedPath;
    folderSelectBtn.dataset.path = selectedPath;
    folderSelectBtnPath.dataset.path = selectedPath;
    folderSelectBtn.style.visibility = "visible";
  } else {
    console.warn("No path found for selected folder");
  }
}

/**
 * @param {MouseEvent} ev
 */
function folderHandleCollapsePress(ev) {
  ev.stopPropagation();

  const target = ev.target.closest('.snaatch-folder-collapse-btn');
  if (!target) {
    console.warn("Could not find collapse button");
    return;
  }

  const folderItem = target.closest('.snaatch-folder-wrapper');
  if (!folderItem) {
    console.warn("Could not find folder wrapper");
    return;
  }

  const hideChildren = folderItem.dataset.childrenVisible === "true";
  const childWrappers = folderItem.querySelectorAll(':scope > .snaatch-folder-wrapper');
  
  for (let child of childWrappers) {
    child.style.display = hideChildren ? 'none' : 'block';
  }

  target.innerHTML = hideChildren ? chevronRightSvg : chevronDownSvg;
  folderItem.dataset.childrenVisible = hideChildren ? "false" : "true";
}

/**
 * @param {Folder[]} folders
 * @param {string} path
 * @param {number} depth
 * @return {HTMLDivElement[]}
 */
function folderCreateItems(folders, path = "/", depth = 0) {
  const addFolderTarget = document.getElementById("snaatch-add-folder-target");
  const initialExpandedPath = addFolderTarget ? addFolderTarget.innerText : "";
  
  return (
    folders
      // remove duplicates by name
      .filter(
        (value, index, self) =>
          index ===
          self.findIndex(
            (t) => t.place === value.place && t.name === value.name
          )
      )
      // sort by name ascending
      .sort((a, b) => a.name.localeCompare(b.name))
      .map((folder) => {
        const newPath = `${path}${folder.name}/`;
        const isExpanded = depth === 0 || 
          (!!initialExpandedPath && (
            initialExpandedPath.startsWith(newPath) ||
            `${initialExpandedPath}/${folder.name}/` === newPath
          ));

        const level = document.createElement("ul");
        level.classList.add("snaatch-folder-wrapper");
        level.dataset.childrenVisible = isExpanded.toString();

        const item = document.createElement("span");
        item.classList.add("snaatch-folder-item");
        item.dataset.path = newPath;
        item.dataset.selected = "false";
        item.innerHTML = `${folderSvg}<span>${folder.name}</span>`;

        item.addEventListener("click", folderHandleFolderPress);

        const addSubfolderBtn = document.createElement("div");
        addSubfolderBtn.innerHTML = newSvg;
        addSubfolderBtn.dataset.path = newPath;
        addSubfolderBtn.addEventListener("click", (e) => {
          e.stopPropagation();
          
          if (isDownloadInProgress) {
            return;
          }

          const currentSubfolderForm = document.getElementById("snaatch-subfolder-form");
          const currentAddFolderTarget = document.getElementById("snaatch-add-folder-target");
          
          if (currentSubfolderForm) {
            currentSubfolderForm.style.visibility = "visible";
          }
          if (currentAddFolderTarget) {
            currentAddFolderTarget.innerText = newPath;
          }
          
          const folderNameInput = document.getElementById("snaatch-folder-name-input");
          if (folderNameInput) {
            folderNameInput.value = "";
            folderNameInput.focus();
          }
        });

        item.append(addSubfolderBtn);

        if (folder.children) {
          item.dataset.hasChildren = "true";
          const collapseButton = document.createElement("div");
          collapseButton.classList.add("snaatch-folder-collapse-btn");
          collapseButton.innerHTML = isExpanded ? chevronDownSvg : chevronRightSvg;
          level.dataset.childrenVisible = isExpanded ? "true" : "false";
          collapseButton.addEventListener("click", folderHandleCollapsePress);
          item.prepend(collapseButton);
        }

        level.append(item);

        if (folder.children) {
          level.append(...folderCreateItems(folder.children, newPath, depth + 1));
        }
        
        return level;
      })
  );
}

/**
 * @param {PathList} pathObject
 * @return {Folder[]}
 */
function folderConvertPathsToTree(pathObject) {
  const pathList = Object.keys(pathObject);

  function innerFunc(paths, pathPrefix = "/") {
    const result = [];
    paths = paths.map((path) => path.replace(/^\//, ""));
    const firstSegments = new Set(paths.map((path) => path.split("/")[0]));

    firstSegments.forEach((segment) => {
      const filteredPaths = paths
        .filter((path) => path.startsWith(`${segment}/`))
        .map((path) => path.replace(`${segment}/`, ""));

      if (!filteredPaths.length) {
        return;
      }

      const res = innerFunc(filteredPaths, `${pathPrefix}${segment}/`);
      result.push({
        name: segment,
        children: res.length ? res : undefined,
      });
    });

    return result;
  }

  return innerFunc(pathList);
}
//endregion

//region Progress Indicator
function ensureOverlayUiStyles() {
  if (document.getElementById("snaatch-overlay-ui-styles")) {
    return;
  }

  const style = document.createElement("style");
  style.id = "snaatch-overlay-ui-styles";
  style.textContent = `
    .snaatch-inline-spinner {
      width: 28px;
      height: 28px;
      border-radius: 50%;
      border: 3px solid rgba(31, 41, 55, 0.16);
      border-top-color: #0f2d45;
      animation: snaatch-spin 0.8s linear infinite;
    }

    .snaatch-progress-fill {
      background-size: 200% 100%;
      animation: snaatch-shimmer 1.8s linear infinite;
    }

    @keyframes snaatch-spin {
      to { transform: rotate(360deg); }
    }

    @keyframes snaatch-shimmer {
      0% { background-position: 200% 0; }
      100% { background-position: -200% 0; }
    }
  `;

  document.head.appendChild(style);
}

/**
 * Initialize the progress indicator
 * @param {number} totalFiles - Total number of files to download
 */
function initializeProgressIndicator(totalFiles) {
  ensureOverlayUiStyles();

  const existingModal = document.getElementById("snaatch-download-progress");
  if (existingModal) {
    existingModal.remove();
  }
  
  const backdrop = document.createElement("div");
  backdrop.id = "snaatch-progress-backdrop";
  backdrop.style.cssText = `
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(17, 24, 39, 0.45);
    backdrop-filter: blur(3px);
    z-index: 9999;
    display: block;
  `;
  
  const progressContainer = document.createElement("div");
  progressContainer.id = "snaatch-download-progress";
  progressContainer.style.cssText = `
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    z-index: 10000;
    padding: 28px;
    background: linear-gradient(180deg, #f8f9fb 0%, #f2f4f7 100%);
    border: 1px solid #d8dde6;
    border-radius: 18px;
    box-shadow: 0 24px 60px rgba(15, 23, 42, 0.28);
    font-family: "Segoe UI", "Helvetica Neue", sans-serif;
    min-width: 450px;
    max-width: 90vw;
    text-align: center;
  `;
  
  progressContainer.innerHTML = `
    <div style="margin-bottom: 18px;">
      <h3 style="margin: 0 0 8px 0; color: #101828; font-size: 20px; font-weight: 650; display: flex; align-items: center; justify-content: center; gap: 12px;">
        Dateien werden importiert
      </h3>
      <div style="font-size: 15px; color: #475467; margin-bottom: 18px;">
        <span id="snaatch-current-files" style="color: #0f2d45; font-weight: 700;">0</span>
        von <span id="snaatch-total-files" style="color: #0f2d45; font-weight: 700;">${totalFiles}</span>
        Dateien abgeschlossen
      </div>
    </div>
    <div style="width: 100%; background-color: #e7ebf1; border-radius: 999px; overflow: hidden; height: 28px; margin-bottom: 14px; position: relative; border: 1px solid #d3d9e4;">
      <div id="snaatch-progress-bar" class="snaatch-progress-fill" style="
        width: 0%; 
        height: 100%; 
        background: linear-gradient(90deg, #0f2d45 0%, #2b5c7f 50%, #0f2d45 100%);
        transition: width 0.3s ease;
      "></div>
      <div id="snaatch-progress-text" style="
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        color: #0f172a;
        font-weight: 700;
        font-size: 14px;
        text-shadow: 0 1px 1px rgba(255,255,255,0.6);
        z-index: 1;
      "></div>
    </div>
    <div style="font-size: 13px; color: #667085;">
      Bitte unterbrechen Sie den Prozess nicht, bis alle Dateien verarbeitet wurden.
    </div>
  `;
  
  document.body.appendChild(backdrop);
  document.body.appendChild(progressContainer);
  
  requestAnimationFrame(() => {
    backdrop.style.display = "block";
    progressContainer.style.display = "block";
    
    currentDisplayedProgress = 0;
    targetProgress = 0;
    currentDisplayedFiles = 0;
    targetFiles = 0;
    
    const progressText = document.getElementById("snaatch-progress-text");
    if (progressText) {
      progressText.textContent = "0%";
    }
    
    backdrop.offsetHeight;
    progressContainer.offsetHeight;
  });
  
  return true;
}

let progressAnimationId = null;
let currentDisplayedProgress = 0;
let targetProgress = 0;
let currentDisplayedFiles = 0;
let targetFiles = 0;

/**
 * Update the progress indicator with smooth animation
 * @param {number} processedFiles - Number of files processed so far
 * @param {number} totalFiles - Total number of files
 * @param {boolean} isProcessing - Whether currently processing files
 */
function updateProgressIndicator(processedFiles, totalFiles, isProcessing = false) {
  const progressContainer = document.getElementById("snaatch-download-progress");
  const progressBar = document.getElementById("snaatch-progress-bar");
  const progressText = document.getElementById("snaatch-progress-text");
  const currentFilesElement = document.getElementById("snaatch-current-files");
  
  if (!progressContainer || !progressBar || !progressText || !currentFilesElement) {
    return;
  }
  
  progressContainer.style.display = "block";
  const backdrop = document.getElementById("snaatch-progress-backdrop");
  if (backdrop) {
    backdrop.style.display = "block";
  }
  
  const percentage = totalFiles > 0 ? (processedFiles / totalFiles) * 100 : 0;
  targetProgress = Math.min(percentage, 100);
  targetFiles = processedFiles;
  
  if (!progressAnimationId) {
    animateProgressSmoothly();
  }
}

/**
 * Animate progress bar smoothly to target value
 */
function animateProgressSmoothly() {
  const progressBar = document.getElementById("snaatch-progress-bar");
  const progressText = document.getElementById("snaatch-progress-text");
  const currentFilesElement = document.getElementById("snaatch-current-files");
  
  if (!progressBar || !progressText || !currentFilesElement) {
    progressAnimationId = null;
    return;
  }
  
  const progressDifference = targetProgress - currentDisplayedProgress;
  const progressStep = progressDifference * 0.05;
  
  const filesDifference = targetFiles - currentDisplayedFiles;
  const filesStep = filesDifference * 0.08;
  
  if (Math.abs(progressDifference) < 0.1) {
    currentDisplayedProgress = targetProgress;
  } else {
    currentDisplayedProgress += progressStep;
  }
  
  if (Math.abs(filesDifference) < 0.1) {
    currentDisplayedFiles = targetFiles;
  } else {
    currentDisplayedFiles += filesStep;
  }
  
  const displayProgress = Math.min(currentDisplayedProgress, 100);
  const displayFiles = Math.round(currentDisplayedFiles);
  
  progressBar.style.width = `${displayProgress}%`;
  progressText.textContent = `${Math.round(displayProgress)}%`;
  currentFilesElement.textContent = displayFiles.toString();
  
  if (displayProgress < 50) {
    progressText.style.color = '#333';
    progressText.style.textShadow = '1px 1px 2px rgba(255,255,255,0.8)';
  } else {
    progressText.style.color = 'white';
    progressText.style.textShadow = '1px 1px 2px rgba(0,0,0,0.8)';
  }
  
  const progressNotReached = Math.abs(targetProgress - currentDisplayedProgress) > 0.1;
  const filesNotReached = Math.abs(targetFiles - currentDisplayedFiles) > 0.1;
  
  if (progressNotReached || filesNotReached) {
    progressAnimationId = requestAnimationFrame(animateProgressSmoothly);
  } else {
    progressAnimationId = null;
  }
}

/**
 * Simulate intermediate progress during chunk processing
 */
function simulateChunkProgress(chunkStartProgress, chunkEndProgress, chunkStartFiles, chunkEndFiles, duration = 2000) {
  const progressBar = document.getElementById("snaatch-progress-bar");
  const progressText = document.getElementById("snaatch-progress-text");
  
  if (!progressBar || !progressText) {
    return Promise.resolve();
  }
  
  return new Promise((resolve) => {
    const startTime = Date.now();
    
    function updateSimulation() {
      const elapsed = Date.now() - startTime;
      const progress = Math.min(elapsed / duration, 1);
      
      const easedProgress = 1 - Math.pow(1 - progress, 3);
      const currentProgress = chunkStartProgress;
      
      targetProgress = Math.min(currentProgress, 100);
      
      if (progress < 1) {
        requestAnimationFrame(updateSimulation);
      } else {
        resolve();
      }
    }
    
    updateSimulation();
  });
}

/**
 * Hide the progress indicator
 */
function hideProgressIndicator() {
  if (progressAnimationId) {
    cancelAnimationFrame(progressAnimationId);
    progressAnimationId = null;
  }
  
  currentDisplayedProgress = 0;
  targetProgress = 0;
  currentDisplayedFiles = 0;
  targetFiles = 0;
  
  const backdrop = document.getElementById("snaatch-progress-backdrop");
  const progressContainer = document.getElementById("snaatch-download-progress");
  
  if (backdrop) {
    backdrop.remove();
  }
  
  if (progressContainer) {
    progressContainer.remove();
  }
}
//endregion

//region File Validation
/**
 * List of supported file extensions
 */
const SUPPORTED_EXTENSIONS = ['gif', 'jpg', 'jpeg', 'tif', 'tiff', 'bmp', 'pcx', 'tga', 'png', 'pdf', 'ai', 'svg'];

/**
 * Show validation modal during file validation
 */
function showValidationModal() {
  ensureOverlayUiStyles();

  const existingModal = document.getElementById("snaatch-validation-modal");
  if (existingModal) {
    existingModal.remove();
  }
  
  const backdrop = document.createElement("div");
  backdrop.id = "snaatch-validation-backdrop";
  backdrop.style.cssText = `
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(17, 24, 39, 0.42);
    backdrop-filter: blur(3px);
    z-index: 9999;
    display: block;
  `;
  
  const validationContainer = document.createElement("div");
  validationContainer.id = "snaatch-validation-modal";
  validationContainer.style.cssText = `
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    z-index: 10000;
    padding: 26px;
    background: linear-gradient(180deg, #fafbfc 0%, #f3f5f8 100%);
    border: 1px solid #d8dde6;
    border-radius: 18px;
    box-shadow: 0 24px 60px rgba(15, 23, 42, 0.28);
    font-family: "Segoe UI", "Helvetica Neue", sans-serif;
    min-width: 400px;
    max-width: 90vw;
    text-align: center;
    display: block;
  `;
  
  validationContainer.innerHTML = `
    <div style="display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px;">
      <span class="snaatch-inline-spinner" aria-hidden="true"></span>
      <span style="font-size: 18px; color: #101828; font-weight: 650;">
        Medien werden geprüft
      </span>
      <span style="font-size: 14px; color: #667085;">
        Bitte einen Moment warten...
      </span>
    </div>
  `;
  
  document.body.appendChild(backdrop);
  document.body.appendChild(validationContainer);
  
  // Force reflow to ensure the modal is rendered
  requestAnimationFrame(() => {
    backdrop.style.display = "block";
    validationContainer.style.display = "block";
    backdrop.offsetHeight; // Force reflow
    validationContainer.offsetHeight; // Force reflow
  });
  
  console.log('Validation modal shown');
  return true;
}

/**
 * Hide validation modal
 */
function hideValidationModal() {
  const backdrop = document.getElementById("snaatch-validation-backdrop");
  const validationContainer = document.getElementById("snaatch-validation-modal");
  
  console.log('Hiding validation modal');
  
  if (backdrop) {
    backdrop.remove();
  }
  
  if (validationContainer) {
    validationContainer.remove();
  }
}

/**
 * Check if a file has a supported extension
 * @param {string} filename - The filename to check
 * @returns {boolean} - True if supported, false otherwise
 */
function isSupportedFileType(filename) {
  if (!filename || typeof filename !== 'string') {
    return false;
  }

  console.log('FileName', filename);
  
  // Clean filename by removing query parameters and converting to lowercase
  const cleanFilename = filename.split('?')[0].toLowerCase().trim();
  
  // Extract extension
  const parts = cleanFilename.split('.');
  if (parts.length < 2) {
    return false; // No extension found
  }
  
  const extension = parts.pop();
  
  return SUPPORTED_EXTENSIONS.includes(extension);
}

/**
 * Validate files and filter out unsupported ones
 * @param {Array} files - Array of file objects to validate
 * @returns {Object} - Object with supported files and unsupported files info
 */
function validateFiles(files) {
  const supportedFiles = [];
  const unsupportedFiles = [];
  
  if (!files || !Array.isArray(files)) {
    return { supportedFiles, unsupportedFiles };
  }
  
  files.forEach(file => {
    const nameFromMetadata = file?.metadata?.name;
    const nameFromSelection = file?.selectionMetadata?.name || file?.selectionMetadata?.filename;
    const fallbackName = nameFromMetadata || nameFromSelection || file?.name || 'Unbekannte Datei';

    let extension = typeof file?.metadata?.extension === 'string'
      ? file.metadata.extension.toLowerCase().trim()
      : '';

    if (!extension && typeof file?.selectionMetadata?.extension === 'string') {
      extension = file.selectionMetadata.extension.toLowerCase().trim();
    }

    if (!extension && typeof fallbackName === 'string' && fallbackName.includes('.')) {
      const parts = fallbackName.split('.');
      extension = (parts.pop() || '').toLowerCase().trim();
    }

    if (!extension && typeof file?.links?.raw === 'string') {
      const cleanUrl = file.links.raw.split('?')[0];
      const urlParts = cleanUrl.split('.');
      if (urlParts.length > 1) {
        extension = (urlParts.pop() || '').toLowerCase().trim();
      }
    }

    const displayFilename = extension && !fallbackName.toLowerCase().endsWith(`.${extension}`)
      ? `${fallbackName}.${extension}`
      : fallbackName;
    const isSupported = SUPPORTED_EXTENSIONS.includes(extension);
    
    // Log available metadata for debugging
    console.log('File validation and metadata:', {
      file: file,
      extension: extension,
      displayFilename: displayFilename,
      dimensions: {
        width: file.metadata?.width || file.width || 'not available',
        height: file.metadata?.height || file.height || 'not available'
      },
      isSupported: isSupported
    });

    // Do not block the first import flow when extension metadata arrives late.
    if (!extension && file?.links?.raw) {
      console.warn('Missing extension metadata, allowing file for first-pass flow:', file);
      supportedFiles.push(file);
      return;
    }

    if (isSupported) {
      supportedFiles.push(file);
    } else {
      unsupportedFiles.push({
        file,
        filename: displayFilename,
        reason: 'Nicht unterstütztes Dateiformat'
      });
    }
  });
  
  return { supportedFiles, unsupportedFiles };
}

/**
 * Create a custom modal dialog
 * @param {string} title - Modal title
 * @param {string} message - Modal message
 * @param {Array} buttons - Array of button configurations
 * @returns {Promise} - Promise that resolves with button name
 */
function createCustomModal(title, message, buttons) {
  return new Promise((resolve) => {
    ensureOverlayUiStyles();

    const existingModal = document.getElementById('snaatch-custom-modal');
    if (existingModal) {
      existingModal.remove();
    }
    
    const backdrop = document.createElement('div');
    backdrop.id = 'snaatch-custom-modal';
    backdrop.style.cssText = `
      position: fixed;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      background: rgba(17, 24, 39, 0.42);
      backdrop-filter: blur(3px);
      z-index: 10001;
      display: flex;
      align-items: center;
      justify-content: center;
    `;
    
    const modal = document.createElement('div');
    modal.style.cssText = `
      background: linear-gradient(180deg, #fafbfc 0%, #f3f5f8 100%);
      border: 1px solid #d8dde6;
      border-radius: 18px;
      box-shadow: 0 24px 60px rgba(15, 23, 42, 0.28);
      font-family: "Segoe UI", "Helvetica Neue", sans-serif;
      min-width: 450px;
      max-width: 600px;
      max-height: 80vh;
      overflow-y: auto;
      padding: 0;
    `;
    
    const header = document.createElement('div');
    header.style.cssText = `
      background: #eef2f7;
      color: #0f172a;
      border-bottom: 1px solid #d9dfe8;
      padding: 16px 20px;
      font-size: 18px;
      font-weight: 650;
      border-radius: 18px 18px 0 0;
      display: flex;
      align-items: center;
      gap: 10px;
    `;
    
    const hasWarning = buttons.some(b => b.type === 'warning');
    const hasError = buttons.some(b => b.type === 'error');
    const tone = hasError ? 'Fehler' : hasWarning ? 'Hinweis' : 'Info';
    header.textContent = `${tone}: ${title}`;
    
    const content = document.createElement('div');
    content.style.cssText = `
      padding: 20px;
      line-height: 1.6;
      white-space: pre-line;
      color: #344054;
      font-size: 14px;
    `;
    content.textContent = message;
    
    const buttonContainer = document.createElement('div');
    buttonContainer.style.cssText = `
      padding: 15px 20px;
      border-top: 1px solid #e0e0e0;
      display: flex;
      gap: 10px;
      justify-content: flex-end;
    `;
    
    buttons.forEach((buttonConfig) => {
      const button = document.createElement('button');
      button.textContent = buttonConfig.text;
      button.setAttribute('data-action', buttonConfig.action);
      
      const isPrimary = buttonConfig.action === 'continue' || buttonConfig.action === 'ok';
      
      button.style.cssText = `
        padding: 10px 18px;
        border: 1px solid transparent;
        border-radius: 10px;
        font-size: 14px;
        font-weight: 600;
        cursor: pointer;
        transition: all 0.2s ease;
        min-width: 100px;
        ${isPrimary ? `
          background: #0f2d45;
          color: #ffffff;
          border-color: #0f2d45;
        ` : `
          background: #ffffff;
          color: #344054;
          border-color: #d0d5dd;
        `}
      `;
      
      button.addEventListener('mouseenter', () => {
        if (isPrimary) {
          button.style.background = '#123a59';
          button.style.borderColor = '#123a59';
        } else {
          button.style.background = '#f2f4f7';
          button.style.borderColor = '#98a2b3';
        }
      });
      
      button.addEventListener('mouseleave', () => {
        if (isPrimary) {
          button.style.background = '#0f2d45';
          button.style.borderColor = '#0f2d45';
        } else {
          button.style.background = '#ffffff';
          button.style.borderColor = '#d0d5dd';
        }
      });
      
      button.addEventListener('click', (e) => {
        e.preventDefault();
        backdrop.remove();
        resolve(buttonConfig.action);
      });
      
      buttonContainer.appendChild(button);
      
      if (isPrimary) {
        setTimeout(() => button.focus(), 100);
      }
    });
    
    const handleEscape = (e) => {
      if (e.key === 'Escape') {
        backdrop.remove();
        document.removeEventListener('keydown', handleEscape);
        resolve('cancel');
      }
    };
    document.addEventListener('keydown', handleEscape);
    
    backdrop.addEventListener('click', (e) => {
      if (e.target === backdrop) {
        backdrop.remove();
        resolve('cancel');
      }
    });
    
    modal.appendChild(header);
    modal.appendChild(content);
    modal.appendChild(buttonContainer);
    backdrop.appendChild(modal);
    
    document.body.appendChild(backdrop);
  });
}

/**
 * Show warning modal for unsupported files
 */
function showUnsupportedFilesWarning(unsupportedFiles, supportedFiles) {
  return new Promise(async (resolve) => {
    const filenames = unsupportedFiles
      .map(item => item.filename || 'Unbekannte Datei')
      .filter(name => name && name.trim() !== '' && name !== 'Unbekannte Datei');
    
    const unsupportedList = filenames.length > 0 
      ? filenames.join('\n• ') 
      : 'Einige Dateien';
    
    const supportedExtensions = SUPPORTED_EXTENSIONS.join(', ').toUpperCase();
    
    let message = '';
    let buttons = [];
    
    if (supportedFiles.length > 0) {
      // FALL 1: Gemischte Auswahl (unterstützte + nicht unterstützte Dateien)
      message = `Folgende Dateien werden nicht unterstützt und können nicht importiert werden:\n\n• ${unsupportedList}\n\n`;
      message += `Unterstützte Formate: ${supportedExtensions}\n\n`;
      message += `Möchten Sie mit dem Import der ${supportedFiles.length} unterstützten Datei(en) fortfahren?`;
      
      buttons = [
        { text: 'Abbrechen', action: 'cancel', type: 'cancel' },
        { text: `${supportedFiles.length} Datei(en) importieren`, action: 'continue', type: 'warning' }
      ];
      
      const result = await createCustomModal(
        'Eine oder mehrere ausgewählte Dateien werden nicht unterstützt',
        message,
        buttons
      );
      
      console.log('User decision for mixed selection:', result);
      resolve(result === 'continue');
      
    } else {
      // FALL 2: Nur nicht unterstützte Dateien (keine unterstützten Dateien vorhanden)
      message = `Folgende Dateien werden nicht unterstützt und können nicht importiert werden:\n\n• ${unsupportedList}\n\n`;
      message += `Unterstützte Formate: ${supportedExtensions}\n\n`;
      message += "Keine der ausgewählten Dateien kann importiert werden.";
      
      buttons = [
        { text: 'OK', action: 'ok', type: 'error' }
      ];
      
      await createCustomModal(
        'Keine unterstützten Dateien',
        message,
        buttons
      );
      
      console.log('User alerted about no supported files');
      resolve(false); // Cancel operation
    }
  });
}
//endregion

async function selectFolderAndStartDownload(files) {
  console.log('selectFolderAndStartDownload called with files:', files);

  if (isSelectionFlowInProgress) {
    console.warn("Selection flow already running, ignoring duplicate message");
    return;
  }

  isSelectionFlowInProgress = true;
  
  // Prevent multiple simultaneous downloads
  if (isDownloadInProgress) {
    console.log("Download already in progress, ignoring new request");
    isSelectionFlowInProgress = false;
    return;
  }

  // Validate file formats before proceeding
  console.log('Starting file validation...');
  
  // Show validation modal
  showValidationModal();
  
  // Add a small delay to ensure the modal is visible
  await new Promise(resolve => setTimeout(resolve, 500));
  
  let validation;
  try {
    validation = validateFiles(files);
    console.log('File validation completed successfully');
    
    // Add another small delay so users can see the validation process
    await new Promise(resolve => setTimeout(resolve, 300));
  } catch (error) {
    console.error('Error during file validation:', error);
    hideValidationModal();
    isSelectionFlowInProgress = false;
    return;
  } finally {
    // Always hide validation modal after validation is complete
    hideValidationModal();
  }
  
  console.log('File validation result:', {
    totalFiles: files.length,
    supportedFiles: validation.supportedFiles.length,
    unsupportedFiles: validation.unsupportedFiles.length,
    unsupportedFilenames: validation.unsupportedFiles.map(f => f.filename)
  });
  
  if (validation.unsupportedFiles.length > 0) {
    console.log('Found unsupported files, showing warning modal...');
    let shouldContinue;
    try {
      shouldContinue = await showUnsupportedFilesWarning(
        validation.unsupportedFiles, 
        validation.supportedFiles
      );
      console.log('Modal result:', shouldContinue);
    } catch (error) {
      console.error('Error showing unsupported files warning:', error);
      isSelectionFlowInProgress = false;
      return;
    }
    
    if (!shouldContinue) {
      console.log("User cancelled due to unsupported files or no supported files found");
      isSelectionFlowInProgress = false;
      return;
    }
    
    // Continue with only supported files (Fall 1)
    console.log(`Continuing with ${validation.supportedFiles.length} supported files`);
    files = validation.supportedFiles;
    console.log('Updated files array after validation:', files);
  }
  
  // Check if we have any files left to process
  if (files.length === 0) {
    console.log("No supported files to process");
    isSelectionFlowInProgress = false;
    return;
  }

  NProgress.start();

  // Download the file from snaatch
  const requestPayload = {
    files: files,  // Use the validated files
  };
  console.log('Request payload:', requestPayload);
  
  new AjaxRequest(TYPO3.settings.ajaxUrls.snaatchDownload)
    .post(requestPayload, {
      headers: {
        "Content-Type": "application/json; charset=utf-8",
      },
    })
    .then(async (response) => {
      const data = await response.resolve();
      console.log(data);

      if (data.subject) {
        switch (data.subject) {
          case "folder-missing":
            console.log('Folder selection required, validated files:', files); // Debug log
            const convertedFolders = folderConvertPathsToTree(data.folders);

            const iframeContainer = document.getElementById("snaatch-iframe-container");
            if (iframeContainer) {
              iframeContainer.style.display = "none";
            }

            NProgress.done();

            function render() {
              const folderSelector = document.getElementById("snaatch-folder-selector");
              if (folderSelector) {
                folderSelector.replaceChildren(
                  ...folderCreateItems(convertedFolders)
                );
              }
            }
            render();

            // Get fresh references to elements
            const folderContainerModal = document.getElementById("snaatch-folder-modal-bg");
            const folderSelectBtn = document.getElementById("snaatch-folder-select-btn");
            const addFolderBtn = document.getElementById("snaatch-add-folder-btn");

            if (!folderContainerModal || !folderSelectBtn || !addFolderBtn) {
              console.error("Required folder modal elements not found");
              isSelectionFlowInProgress = false;
              return;
            }

            // Clear any existing event listeners by cloning and replacing
            const newFolderSelectBtn = folderSelectBtn.cloneNode(true);
            folderSelectBtn.parentNode.replaceChild(newFolderSelectBtn, folderSelectBtn);

            const newAddFolderBtn = addFolderBtn.cloneNode(true);
            addFolderBtn.parentNode.replaceChild(newAddFolderBtn, addFolderBtn);

            // Capture the validated files in a closure for the event handler
            const validatedFiles = [...files]; // Create a copy to ensure it's captured correctly
            console.log('Captured files for event handlers:', validatedFiles);

            // Event listener for folder selection - use persistent handler
            newFolderSelectBtn.addEventListener("click", async function handleFolderSelect(event) {
              event.preventDefault();
              event.stopImmediatePropagation();
              
              if (isDownloadInProgress) {
                return;
              }
              
              const selectedFolder = newFolderSelectBtn.dataset.path;

              if (!selectedFolder) {
                await createCustomModal(
                  'Kein Ordner ausgewählt',
                  'Bitte wählen Sie einen Ordner aus.',
                  [{ text: 'OK', action: 'ok', type: 'error' }]
                );
                return;
              }

              console.log("Selected folder", selectedFolder);
              console.log("Files to download:", validatedFiles); // Use validatedFiles instead of files
              console.log("Files array length:", validatedFiles.length);
              
              // Set download in progress flag
              isDownloadInProgress = true;
              
              // Hide the folder selection modal immediately when download starts
              folderContainerModal.style.display = "none";
              
              // Start download with error handling for progress indicator
              downloadFiles(validatedFiles, selectedFolder).catch((error) => { // Use validatedFiles
                console.error("Download failed:", error);
                hideProgressIndicator();
                isDownloadInProgress = false; // Reset flag on error
                // Re-show folder modal on error
                folderContainerModal.style.display = "block";
              }).finally(() => {
                isDownloadInProgress = false; // Reset flag when done
              });
            });

            // Event listener for add folder - use persistent handler
            newAddFolderBtn.addEventListener("click", async function handleAddFolderBtnPress(event) {
              event.preventDefault();
              event.stopImmediatePropagation();
              
              if (isDownloadInProgress) {
                return;
              }
              
              const folderNameInput = document.getElementById("snaatch-folder-name-input");
              const addFolderTarget = document.getElementById("snaatch-add-folder-target");
              const subfolderForm = document.getElementById("snaatch-subfolder-form");
              
              const folderName = folderNameInput ? folderNameInput.value : "";
              if (!folderName) {
                await createCustomModal(
                  'Ordnername fehlt',
                  'Bitte geben Sie einen Ordnernamen ein.',
                  [{ text: 'OK', action: 'ok', type: 'error' }]
                );
                return;
              }
              const target = addFolderTarget ? addFolderTarget.innerText : "";

              // split into path parts and remove empty entries (because of leading and trailing slash)
              const pathParts = target.split("/").filter((x) => !!x);

              if (!pathParts.length) {
                await createCustomModal(
                  'Ordner konnte nicht erstellt werden',
                  'Der Ordner konnte nicht erstellt werden.',
                  [{ text: 'OK', action: 'ok', type: 'error' }]
                );
                return;
              }

              const rootFolderPath = pathParts.shift();
              let destinationFolder = convertedFolders.find(
                (x) => x.name === rootFolderPath
              );
              while (pathParts.length) {
                const path = pathParts.shift();
                destinationFolder = destinationFolder.children.find(
                  (x) => x.name === path
                );
              }

              if (!destinationFolder.children) {
                destinationFolder.children = [];
              }

              destinationFolder.children.push({
                name: folderName,
                children: undefined,
              });

              render();
              if (subfolderForm) {
                subfolderForm.style.visibility = "hidden";
              }
              
              // Clear the input field after adding folder
              if (folderNameInput) {
                folderNameInput.value = "";
              }

              setTimeout(async () => {
                await createCustomModal(
                  'Ordner hinzugefügt',
                  'Der Ordner wurde hinzugefügt.',
                  [{ text: 'OK', action: 'ok', type: 'info' }]
                );
              }, 100);
            });
            
            folderContainerModal.style.display = "block";
            isSelectionFlowInProgress = false;
            return;
          default:
            console.error("Unknown subject", data.subject);
            NProgress.done();
            isSelectionFlowInProgress = false;
            return;
        }
      }

      // Show an error modal
      const confirm = Modal.confirm("error", data.error, Severity.error, [
        {
          // @ts-ignore
          text: TYPO3.lang["button.ok"] || "OK",
          btnClass: "btn-" + Severity.getCssClass(Severity.error),
          name: "ok",
          active: true,
        },
      ]);

      confirm.on("confirm.button.ok", () => {
        confirm.modal("hide");
      });

      NProgress.done();

      isSelectionFlowInProgress = false;
    })
    .catch((error) => {
      console.error("Error in selectFolderAndStartDownload:", error);
      isDownloadInProgress = false;
      NProgress.done();
      isSelectionFlowInProgress = false;
    })
    .finally(() => {
      const folderContainer = document.getElementById("snaatch-folder-container");
      // Only clean up if we're not in the middle of a download
      if (!isDownloadInProgress && folderContainer) {
        folderContainer.classList.remove("loading");
      }

      if (!isDownloadInProgress) {
        isSelectionFlowInProgress = false;
      }
    });
}

async function downloadFiles(files, folder) {
  // IMMEDIATELY hide the folder selection modal - use correct ID
  const folderModal = document.getElementById("snaatch-folder-modal-bg");
  if (folderModal) {
    folderModal.style.display = "none";
  }
  
  // chunk the files into groups of 5
  const chunkSize = 5;
  const fileChunks = [];
  for (let i = 0; i < files.length; i += chunkSize) {
    fileChunks.push(files.slice(i, i + chunkSize));
  }

  // Initialize progress indicator with total file count
  const progressInitialized = initializeProgressIndicator(files.length);
  
  if (!progressInitialized) {
    return;
  }
  
  // Wait a moment to ensure the progress modal is fully rendered
  await new Promise(resolve => setTimeout(resolve, 100));

  try {
    let processedFiles = 0;
    
    for (let chunkIndex = 0; chunkIndex < fileChunks.length; chunkIndex++) {
      const chunk = fileChunks[chunkIndex];
      
      // Calculate progress percentages for this chunk
      const chunkStartProgress = (processedFiles / files.length) * 100;
      const chunkEndProgress = ((processedFiles + chunk.length) / files.length) * 100;
      
      // Start chunk with current progress
      updateProgressIndicator(processedFiles, files.length, true);
      
      // Simulate smooth progress during chunk processing (progress bar only)
      const progressSimulation = simulateChunkProgress(
        chunkStartProgress, 
        chunkEndProgress, 
        processedFiles, 
        processedFiles + chunk.length, 
        1500
      );
      
      // Download the files in the chunk (run in parallel with progress simulation)
      const [downloadResult] = await Promise.all([
        downloadFilesCore(chunk, folder),
        progressSimulation
      ]);
      
      // Update processed files count ONLY AFTER chunk completion
      processedFiles += chunk.length;
      
      // Set final progress for this chunk (both progress bar and file counter)
      updateProgressIndicator(processedFiles, files.length, false);
      
      // Small pause to let the final progress update be visible
      await new Promise(resolve => setTimeout(resolve, 300));
    }
    
    // Close all modals and hide UI elements after ALL chunks are done
    
    // Ensure the folder modal stays hidden
    if (folderModal) {
      folderModal.style.display = "none";
    }
    
    // Hide the iframe again
    const iframeContainer = document.getElementById("snaatch-iframe-container");
    if (iframeContainer) {
      iframeContainer.style.display = "none";
    }
    
    // Remove any loading states
    const folderContainer = document.getElementById("snaatch-folder-container");
    if (folderContainer) {
      folderContainer.classList.remove("loading");
    }
    
    // Hide progress indicator when complete
    setTimeout(() => {
      hideProgressIndicator();
    }, 1000); // Keep visible for 1 second to show completion
    
  } catch (error) {
    console.error("Error during chunk download:", error);
    hideProgressIndicator();
    
    // Re-show folder modal only on error
    if (folderModal) {
      folderModal.style.display = "block";
    }
    
    throw error; // Re-throw to handle in calling function
  }
}

/**
 * List of supported file extensions
 */
const UNSUPPORTED_RESOLUTION = ['pdf'];


function downloadFilesCore(files, folder) {
  // Prepare files with metadata including dimensions
  const filesWithMetadata = files.map(file => {
    const fileData = { ...file };
    
    // Extract image dimensions from metadata if available
    if (file.metadata) {
      if (file.metadata.width && file.metadata.height && !UNSUPPORTED_RESOLUTION.includes(file.metadata.extension)) {
        fileData.imageDimensions = {
          width: parseInt(file.metadata.width, 10),
          height: parseInt(file.metadata.height, 10)
        };
        console.log(`Image dimensions for ${file.metadata.name}: ${fileData.imageDimensions.width}x${fileData.imageDimensions.height}`);
      } else if (file.width && file.height) {
        // Fallback: check for dimensions directly on file object
        fileData.imageDimensions = {
          width: parseInt(file.width, 10),
          height: parseInt(file.height, 10)
        };
        console.log(`Image dimensions (fallback) for ${file.metadata?.name || 'unknown'}: ${fileData.imageDimensions.width}x${fileData.imageDimensions.height}`);
      } else {
        console.log(`No image dimensions found for ${file.metadata?.name || 'unknown'}`);
      }
    }
    
    return fileData;
  });

  // Download the file from snaatch
  const requestPayload = {
    files: filesWithMetadata,
    folder: folder,
  };

  return new AjaxRequest(TYPO3.settings.ajaxUrls.snaatchDownload)
    .post(requestPayload, {
      headers: {
        "Content-Type": "application/json; charset=utf-8",
      },
    })
    .then(async (response) => {
      const data = await response.resolve();

      if (data.files.length) {
        // Add each file to the file table
        data.files.forEach((uid) => {
          MessageUtility.send({
            actionName: "typo3:foreignRelation:insert",
            objectGroup: document
              .getElementById("snaatch-btn")
              .getAttribute("data-dom"),
            table: "sys_file",
            uid: uid,
          });
        });
      } else {
        // Show an error modal
        const confirm = Modal.confirm("error", data.error, Severity.error, [
          {
            // @ts-ignore
            text: TYPO3.lang["button.ok"] || "OK",
            btnClass: "btn-" + Severity.getCssClass(Severity.error),
            name: "ok",
            active: true,
          },
        ]);

        confirm.on("confirm.button.ok", () => {
          confirm.modal("hide");
        });
        
        throw new Error(`Download failed: ${data.error}`);
      }
    })
    .finally(() => {
      // Clean up any loading states
      const folderContainer = document.getElementById("snaatch-folder-container");
      if (folderContainer) {
        folderContainer.classList.remove("loading");
      }
    });
}
