// Tailwind file/media uploader helpers (dropzone, simple input, photo preview)
(function () {
  const icon = (name, cls = "w-5 h-5") => {
    if (window.tailwindIcon) return window.tailwindIcon(name, cls);
    if (window.lucide && window.lucide.icons && window.lucide.icons[name]) {
      const svg = window.lucide.createElement(window.lucide.icons[name]);
      svg.setAttribute("class", cls);
      return svg.outerHTML;
    }
    return "";
  };

  function showUploadError(message) {
    if (window.toaster && typeof window.toaster.error === "function") {
      window.toaster.error(message);
      return;
    }
    alert(message);
  }

  function parseAcceptList(accept) {
    if (!accept) return [];
    return accept
      .split(",")
      .map((item) => item.trim())
      .filter(Boolean);
  }

  function fileMatchesAccept(file, acceptList) {
    if (!acceptList.length) return true;
    const name = (file.name || "").toLowerCase();
    const type = (file.type || "").toLowerCase();
    return acceptList.some((rule) => {
      if (!rule) return false;
      if (rule.endsWith("/*")) {
        const prefix = rule.replace("/*", "");
        return type.startsWith(prefix);
      }
      if (rule.startsWith(".")) {
        return name.endsWith(rule.toLowerCase());
      }
      return type === rule.toLowerCase();
    });
  }

  function getValidationRules(input, type) {
    const dataset = input ? input.dataset : {};
    const accept = (input && input.getAttribute("accept")) || dataset.accept || "";
    const maxSizeMb = dataset.maxSize ? parseFloat(dataset.maxSize) : null;
    const maxBytes = dataset.maxBytes ? parseInt(dataset.maxBytes, 10) : null;
    return {
      acceptList: parseAcceptList(accept),
      maxBytes: Number.isFinite(maxBytes) ? maxBytes : (Number.isFinite(maxSizeMb) ? maxSizeMb * 1024 * 1024 : null),
      requireImage: type === "photo",
    };
  }

  function validateFile(file, rules) {
    if (rules.requireImage && (!file.type || !file.type.startsWith("image/"))) {
      return "Only image files are allowed.";
    }
    if (rules.acceptList.length && !fileMatchesAccept(file, rules.acceptList)) {
      return "File type is not allowed.";
    }
    if (rules.maxBytes && file.size > rules.maxBytes) {
      const mb = Math.ceil(rules.maxBytes / 1024 / 1024);
      return `File is too large. Max ${mb} MB.`;
    }
    return null;
  }

  class TailwindDropzone {
    constructor(el) {
      this.dropzone = el;
      this.input = this.dropzone.querySelector("input[type='file']");
      this.list = document.querySelector(this.dropzone.dataset.listTarget || "#upload-list");
      this.form = this.dropzone.closest("form");
      this.withComment = this.dropzone.dataset.comment === "true";
      this.uploadUrl =
        this.dropzone.dataset.uploadUrl ||
        (window.appConfig && (window.appConfig.base_url || window.appConfig.baseUrl)
          ? (window.appConfig.base_url || window.appConfig.baseUrl) + "admin/common/upload_file"
          : "/admin/common/upload_file");
      this.validateUrl =
        this.dropzone.dataset.validateUrl ||
        (window.appConfig && (window.appConfig.base_url || window.appConfig.baseUrl)
          ? (window.appConfig.base_url || window.appConfig.baseUrl) + "admin/common/validate_project_file"
          : "/admin/common/validate_project_file");
      this.deleteUrl =
        this.dropzone.dataset.deleteUrl ||
        (window.appConfig && (window.appConfig.base_url || window.appConfig.baseUrl)
          ? (window.appConfig.base_url || window.appConfig.baseUrl) + "admin/common/delete_temp_file"
          : "/admin/common/delete_temp_file");
      this.fileIndex = 0;
      this.init();
    }
    init() {
      if (!this.input || !this.list) return;
      ["dragenter", "dragover", "dragleave", "drop"].forEach((evt) => {
        this.dropzone.addEventListener(evt, (e) => {
          e.preventDefault();
          e.stopPropagation();
        });
      });
      ["dragenter", "dragover"].forEach((evt) => {
        this.dropzone.addEventListener(evt, () => this.dropzone.classList.add("dropzone-active"));
      });
      ["dragleave", "drop"].forEach((evt) => {
        this.dropzone.addEventListener(evt, () => this.dropzone.classList.remove("dropzone-active"));
      });
      this.dropzone.addEventListener("drop", (e) => this.handleFiles(e.dataTransfer.files));
      this.input.addEventListener("change", (e) => {
        this.handleFiles(e.target.files);
        this.input.value = "";
      });

      const iconHolder = this.dropzone.querySelector(".upload-icon-container");
      if (iconHolder) iconHolder.innerHTML = icon("UploadCloud", "w-6 h-6");
    }
    handleFiles(files) {
      const rules = getValidationRules(this.input, "dropzone");
      Array.from(files || []).forEach((file) => {
        const error = validateFile(file, rules);
        if (error) {
          showUploadError(error);
          return;
        }
        this.prepareUpload(file);
      });
    }
    prepareUpload(file) {
      const row = document.createElement("div");
      row.className =
        "upload-row flex items-center gap-3 p-3 bg-slate-50 dark:bg-slate-700/50 rounded-lg border border-slate-200 dark:border-slate-700 relative overflow-hidden";
      if (this.withComment) {
        row.classList.add("flex-col", "items-stretch");
      }
      const iconName = file.type && file.type.startsWith("image/") ? "Image" : "File";
      row.innerHTML = `
        <div class="flex w-full items-center gap-3">
          <div class="flex-shrink-0 text-slate-400 dark:text-slate-500">${icon(iconName, "w-5 h-5")}</div>
          <div class="flex-1 min-w-0 z-10">
            <div class="flex justify-between mb-1">
              <p class="text-sm font-medium text-slate-700 dark:text-slate-200 truncate">${file.name}</p>
              <span class="text-xs text-slate-500 percentage">0%</span>
            </div>
            <div class="w-full bg-slate-200 dark:bg-slate-600 rounded-full h-1.5">
              <div class="bg-blue-600 h-1.5 rounded-full transition-all duration-300 progress-bar" style="width:0%"></div>
            </div>
          </div>
          <button type="button" class="z-10 text-slate-400 hover:text-red-500 transition-colors remove-upload">${icon("Trash2", "w-4 h-4")}</button>
        </div>
      `;
      if (this.withComment) {
        const commentWrap = document.createElement("div");
        commentWrap.className = "mt-3 w-full";
        commentWrap.innerHTML = `
          <textarea rows="2"
            class="w-full rounded-lg border border-slate-200 bg-white px-3 py-2 text-sm text-slate-700 focus:border-slate-400 focus:outline-none dark:border-slate-600 dark:bg-slate-900 dark:text-slate-200"
            placeholder="comments"></textarea>
        `;
        row.appendChild(commentWrap);
      }
      this.list.appendChild(row);
      row.querySelector(".remove-upload").onclick = () => this.removeRow(row);
      this.validateAndUpload(file, row);
    }
    setProgress(row, value) {
      const bar = row.querySelector(".progress-bar");
      const perc = row.querySelector(".percentage");
      const width = Math.max(0, Math.min(100, value));
      bar.style.width = width + "%";
      if (width < 100) {
        perc.textContent = Math.round(width) + "%";
      } else {
        perc.textContent = "Completed";
        perc.classList.add("text-green-600");
        bar.classList.add("bg-green-500");
      }
    }
    validateAndUpload(file, row) {
      const body = new URLSearchParams();
      body.set("file_name", file.name);
      body.set("file_size", file.size);
      fetch(this.validateUrl, {
        method: "POST",
        headers: { "X-Requested-With": "XMLHttpRequest" },
        body,
      })
        .then((res) => res.json())
        .then((payload) => {
          if (!payload || payload.success !== true) {
            showUploadError(payload && payload.message ? payload.message : "File not allowed.");
            row.remove();
            return;
          }
          this.uploadFile(file, row);
        })
        .catch(() => {
          showUploadError("Could not validate file.");
          row.remove();
        });
    }
    uploadFile(file, row) {
      const formData = new FormData();
      formData.append("file", file);
      const xhr = new XMLHttpRequest();
      row.dataset.xhr = "true";
      row._xhr = xhr;
      xhr.open("POST", this.uploadUrl, true);
      xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
      xhr.upload.addEventListener("progress", (e) => {
        if (!e.lengthComputable) return;
        const percent = (e.loaded / e.total) * 100;
        this.setProgress(row, percent);
      });
      xhr.addEventListener("load", () => {
        if (xhr.status >= 200 && xhr.status < 300) {
          let payload = null;
          try {
            payload = JSON.parse(xhr.responseText);
          } catch (err) {
            payload = null;
          }
          if (payload && payload.success === false) {
            showUploadError(payload.message || "Upload failed.");
            row.remove();
            return;
          }
          if (payload && payload.temp_name) {
            row.dataset.tempName = payload.temp_name;
          }
          this.setProgress(row, 100);
          this.attachHiddenFields(file, row);
          return;
        }
        showUploadError("Upload failed.");
        row.remove();
      });
      xhr.addEventListener("error", () => {
        showUploadError("Upload failed.");
        row.remove();
      });
      xhr.send(formData);
    }
    attachHiddenFields(file, row) {
      if (!this.form) return;
      this.fileIndex += 1;
      const fileId = String(this.fileIndex);
      const tempName = row.dataset.tempName || file.name;
      row.dataset.fileId = fileId;

      const filesInput = document.createElement("input");
      filesInput.type = "hidden";
      filesInput.name = "files[]";
      filesInput.value = fileId;

      const nameInput = document.createElement("input");
      nameInput.type = "hidden";
      nameInput.name = `file_name_${fileId}`;
      nameInput.value = tempName;

      const sizeInput = document.createElement("input");
      sizeInput.type = "hidden";
      sizeInput.name = `file_size_${fileId}`;
      sizeInput.value = file.size;

      row.appendChild(filesInput);
      row.appendChild(nameInput);
      row.appendChild(sizeInput);

      if (this.withComment) {
        const textarea = row.querySelector("textarea");
        if (textarea) {
          textarea.name = `comment_${fileId}`;
        }
      }
    }
    removeRow(row) {
      if (row && row._xhr && row._xhr.readyState !== 4) {
        row._xhr.abort();
      }
      const tempName = row ? row.dataset.tempName : "";
      if (tempName) {
        const body = new URLSearchParams();
        body.set("file_name", tempName);
        fetch(this.deleteUrl, {
          method: "POST",
          headers: { "X-Requested-With": "XMLHttpRequest" },
          body,
        }).catch(() => {});
      }
      row.remove();
    }
  }

  function initSimpleUpload() {
    document.querySelectorAll("[data-file-upload]").forEach((wrap) => {
      const input = wrap.querySelector("input[type='file']");
      const text = wrap.querySelector("[data-file-target]");
      if (!input || !text) return;
      let removeBtn = wrap.querySelector("[data-file-remove]");
      if (!removeBtn) {
        removeBtn = document.createElement("button");
        removeBtn.type = "button";
        removeBtn.dataset.fileRemove = "true";
        removeBtn.className =
          "ml-0 2xl:ml-2 inline-flex h-9 w-9 items-center justify-center rounded-lg border border-slate-200 bg-white text-slate-500 hover:text-red-500 hover:border-red-200 transition-colors";
        removeBtn.innerHTML = icon("Trash2", "w-4 h-4");
        text.parentElement && text.parentElement.appendChild(removeBtn);
      }
      const clearSimple = () => {
        input.value = "";
        text.value = "";
        removeBtn.classList.add("hidden");
      };
      removeBtn.addEventListener("click", clearSimple);
      removeBtn.classList.add("hidden");
      input.addEventListener("change", (e) => {
        const file = e.target.files[0];
        if (!file) {
          text.value = "";
          removeBtn.classList.add("hidden");
          return;
        }
        const rules = getValidationRules(input, "file");
        const error = validateFile(file, rules);
        if (error) {
          showUploadError(error);
          input.value = "";
          text.value = "";
          removeBtn.classList.add("hidden");
          return;
        }
        text.value = file.name;
        removeBtn.classList.remove("hidden");
      });
    });
  }

  function initPhotoUpload() {
    document.querySelectorAll("[data-photo-upload]").forEach((wrap) => {
      if (wrap.dataset.photoUploadReady === "1") return;
      const input = wrap.querySelector("input[type='file']");
      const img = wrap.querySelector("[data-photo-img]");
      const placeholder = wrap.querySelector("[data-photo-placeholder]");
      const btnText = wrap.querySelector("[data-photo-btn-text]");
      const removeBtn = wrap.querySelector("[data-photo-remove]");
      const previewBox = wrap.querySelector(".photo-uploader-container");
      if (!input || !img || !placeholder || !btnText || !removeBtn || !previewBox) return;
      wrap.dataset.photoUploadReady = "1";

      const previewStage = previewBox.querySelector(".photo-preview") || previewBox;
      previewStage.classList.add("relative");
      removeBtn.classList.add(
        "absolute",
        "top-2",
        "right-2",
        "z-10",
        "hidden",
        "bg-white/90",
        "text-slate-600",
        "hover:text-red-600",
        "border",
        "border-slate-200",
        "dark:bg-slate-900/90",
        "dark:border-slate-700",
        "dark:text-slate-200",
        "rounded-full",
        "p-1.5",
        "shadow-sm"
      );
      if (!previewStage.contains(removeBtn)) {
        previewStage.appendChild(removeBtn);
      }

      const showRemove = (show) => {
        if (input.value) {
          removeBtn.classList.toggle("hidden", !show);
        }
      };

      previewBox.addEventListener("click", (e) => {
        if (e.target === input) return;
        if (e.target.closest("[data-photo-remove]")) return;
        input.click();
      });

      previewBox.addEventListener("mouseenter", () => showRemove(true));
      previewBox.addEventListener("mouseleave", () => showRemove(false));

      input.addEventListener("change", function () {
        const file = this.files[0];
        if (file) {
          const rules = getValidationRules(input, "photo");
          const error = validateFile(file, rules);
          if (error) {
            showUploadError(error);
            input.value = "";
            img.src = "";
            img.classList.add("hidden");
            placeholder.classList.remove("hidden");
            btnText.textContent = "Select Image";
            removeBtn.classList.add("hidden");
            return;
          }
        }
        if (file) {
          const reader = new FileReader();
          reader.onload = (e) => {
            img.src = e.target.result;
            img.classList.remove("hidden");
            placeholder.classList.add("hidden");
            btnText.textContent = "Change";
            showRemove(false);
          };
          reader.readAsDataURL(file);
        }
      });

      removeBtn.addEventListener("click", () => {
        input.value = "";
        img.src = "";
        img.classList.add("hidden");
        placeholder.classList.remove("hidden");
        btnText.textContent = "Select Image";
        removeBtn.classList.add("hidden");
      });
    });
  }

  function initDropzones() {
    document.querySelectorAll(".tw-dropzone").forEach((el) => new TailwindDropzone(el));
  }

  function initUploader() {
    initDropzones();
    initSimpleUpload();
    initPhotoUpload();
  }

  if (document.readyState === "interactive" || document.readyState === "complete") {
    initUploader();
  } else {
    document.addEventListener("DOMContentLoaded", initUploader);
  }

  window.initUploader = initUploader;
})();
