(async function initMenuAdmin() {
  if (!document.body.classList.contains("menu-admin-page")) {
    return;
  }

  if (!window.MenuStore) {
    return;
  }

  const categoryListNode = document.querySelector("[data-admin-category-list]");
  const editorNode = document.querySelector("[data-admin-editor]");
  const saveButton = document.querySelector("[data-admin-save]");
  const exportButton = document.querySelector("[data-admin-export]");
  const importInput = document.querySelector("[data-admin-import-file]");
  const resetButton = document.querySelector("[data-admin-reset]");
  const addItemButton = document.querySelector("[data-admin-add-item]");
  const statusNode = document.querySelector("[data-admin-status]");

  if (
    !categoryListNode ||
    !editorNode ||
    !saveButton ||
    !exportButton ||
    !importInput ||
    !resetButton ||
    !addItemButton ||
    !statusNode
  ) {
    return;
  }

  let menuData = null;
  let activeCategoryId = null;
  let isDirty = false;
  let essentialModalState = null;

  const setStatus = (message, mode = "info") => {
    statusNode.textContent = message;
    statusNode.dataset.mode = mode;
  };

  const getErrorMessage = (error, fallbackMessage) => {
    if (!error) {
      return fallbackMessage;
    }

    const raw = typeof error?.message === "string" ? error.message.trim() : "";
    if (!raw) {
      return fallbackMessage;
    }

    return raw
      .replace(/[{}"]/g, " ")
      .replace(/\s+/g, " ")
      .trim();
  };

  const getServerHint = () => {
    if (window.location.protocol === "file:") {
      return "Abre esta página con dev_server.py: http://127.0.0.1:4173/admin-carta.html";
    }
    return "Verifica que el servidor esté activo y que ./api/menu.php (o ./api/menu) responda.";
  };

  if (window.location.protocol === "file:") {
    setStatus("Modo local detectado. Para guardar en archivo usa dev_server.py.", "warn");
  }

  const markDirty = () => {
    isDirty = true;
    setStatus("Cambios sin guardar.", "warn");
  };

  const getActiveCategory = () =>
    menuData.categories.find((category) => category.id === activeCategoryId) || menuData.categories[0];

  const createEmptyItem = (category) => {
    const timestamp = Date.now();
    return {
      id: `${category.id}-${timestamp}`,
      tag: "Nuevo",
      name: "Nuevo producto",
      description: "Describe aquí este producto.",
      price: "0,00 €",
      badge: "Editar badge",
      image: "./assets/milkshake.webp",
      alt: "Producto de carta",
      essential: false
    };
  };

  const getEssentialEntries = () => {
    if (!menuData?.categories?.length) {
      return [];
    }

    const entries = [];
    menuData.categories.forEach((category) => {
      category.items.forEach((item, itemIndex) => {
        if (!item?.essential) {
          return;
        }
        entries.push({
          categoryId: category.id,
          categoryLabel: category.label,
          itemIndex,
          item
        });
      });
    });
    return entries;
  };

  const findCategoryById = (categoryId) =>
    menuData.categories.find((category) => category.id === categoryId) || null;

  const ensureEssentialModal = () => {
    let modal = document.querySelector("[data-admin-essential-modal]");
    if (modal) {
      return modal;
    }

    modal = document.createElement("div");
    modal.className = "menu-admin-modal";
    modal.hidden = true;
    modal.setAttribute("data-admin-essential-modal", "");
    modal.innerHTML = `
      <div class="menu-admin-modal__backdrop" data-admin-essential-cancel></div>
      <div class="menu-admin-modal__card" role="dialog" aria-modal="true" aria-labelledby="admin-essential-title">
        <h3 id="admin-essential-title">Descarta un imprescindible seleccionado</h3>
        <p>Solo puedes tener 4 imprescindibles en home. Elige cuál quitar para añadir el nuevo.</p>
        <p class="menu-admin-modal__pending">Se intenta añadir: <strong data-admin-essential-pending-name></strong></p>
        <ul class="menu-admin-modal__list" data-admin-essential-list></ul>
        <p class="menu-admin-modal__swap" data-admin-essential-swap hidden></p>
        <div class="menu-admin-modal__actions">
          <button type="button" class="btn btn-secondary" data-admin-essential-cancel>Cancelar</button>
          <button type="button" class="btn btn-primary" data-admin-essential-confirm disabled>OK</button>
        </div>
      </div>
    `;
    document.body.appendChild(modal);
    return modal;
  };

  const closeEssentialModal = () => {
    const modal = ensureEssentialModal();
    modal.hidden = true;
    essentialModalState = null;
  };

  const renderEssentialModal = () => {
    const modal = ensureEssentialModal();
    const listNode = modal.querySelector("[data-admin-essential-list]");
    const pendingNameNode = modal.querySelector("[data-admin-essential-pending-name]");
    const swapNode = modal.querySelector("[data-admin-essential-swap]");
    const confirmButton = modal.querySelector("[data-admin-essential-confirm]");
    if (!listNode || !pendingNameNode || !swapNode || !confirmButton || !essentialModalState?.pending) {
      return;
    }

    const essentials = getEssentialEntries();
    const pending = essentialModalState.pending;
    const selectedDiscard = essentialModalState.discard;

    pendingNameNode.textContent = pending.itemName;
    listNode.innerHTML = essentials
      .map((entry) => {
        const isSelectedDiscard =
          selectedDiscard &&
          selectedDiscard.categoryId === entry.categoryId &&
          selectedDiscard.itemIndex === entry.itemIndex;
        return `
          <li class="menu-admin-modal__item${isSelectedDiscard ? " is-discarded" : ""}">
            <div class="menu-admin-modal__item-copy">
              <strong>${entry.item.name}</strong>
              <small>${entry.categoryLabel}</small>
            </div>
            <button
              type="button"
              class="menu-admin-modal__remove"
              data-admin-essential-discard
              data-category-id="${entry.categoryId}"
              data-item-index="${entry.itemIndex}"
              aria-label="Descartar ${entry.item.name}"
              title="Descartar"
            >✕</button>
          </li>
        `;
      })
      .join("");

    if (selectedDiscard) {
      swapNode.hidden = false;
      swapNode.textContent = `Entrará: ${pending.itemName}`;
    } else {
      swapNode.hidden = true;
      swapNode.textContent = "";
    }

    confirmButton.disabled = !selectedDiscard;
    modal.hidden = false;
  };

  const openEssentialModal = (pendingCategoryId, pendingItemIndex) => {
    const category = findCategoryById(pendingCategoryId);
    const item = category?.items?.[pendingItemIndex];
    if (!category || !item) {
      return;
    }

    essentialModalState = {
      pending: {
        categoryId: pendingCategoryId,
        itemIndex: pendingItemIndex,
        itemName: item.name
      },
      discard: null
    };

    renderEssentialModal();
  };

  const initEssentialModalEvents = () => {
    const modal = ensureEssentialModal();
    modal.addEventListener("click", (event) => {
      const cancelNode = event.target.closest("[data-admin-essential-cancel]");
      if (cancelNode) {
        closeEssentialModal();
        renderEditor();
        initMediaFallback(editorNode);
        return;
      }

      const discardNode = event.target.closest("[data-admin-essential-discard]");
      if (discardNode && essentialModalState?.pending) {
        const categoryId = discardNode.getAttribute("data-category-id");
        const itemIndex = Number(discardNode.getAttribute("data-item-index"));
        if (!categoryId || !Number.isInteger(itemIndex)) {
          return;
        }
        essentialModalState.discard = {
          categoryId,
          itemIndex
        };
        renderEssentialModal();
        return;
      }

      const confirmNode = event.target.closest("[data-admin-essential-confirm]");
      if (confirmNode && essentialModalState?.pending && essentialModalState.discard) {
        const { pending, discard } = essentialModalState;
        const pendingCategory = findCategoryById(pending.categoryId);
        const discardCategory = findCategoryById(discard.categoryId);
        const pendingItem = pendingCategory?.items?.[pending.itemIndex];
        const discardItem = discardCategory?.items?.[discard.itemIndex];
        if (!pendingItem || !discardItem) {
          closeEssentialModal();
          renderEditor();
          initMediaFallback(editorNode);
          return;
        }

        discardItem.essential = false;
        pendingItem.essential = true;
        closeEssentialModal();
        renderEditor();
        initMediaFallback(editorNode);
        markDirty();
        setStatus("Imprescindible actualizado. Pulsa guardar para reflejarlo en home.", "warn");
      }
    });
  };

  const renderCategoryList = () => {
    categoryListNode.innerHTML = menuData.categories
      .map((category) => {
        const isActive = category.id === activeCategoryId;
        return `
          <button
            type="button"
            class="menu-admin-category-btn${isActive ? " is-active" : ""}"
            data-admin-category="${category.id}"
          >${category.label}</button>
        `;
      })
      .join("");
  };

  const renderEditor = () => {
    const category = getActiveCategory();
    if (!category) {
      editorNode.innerHTML = "";
      return;
    }

    editorNode.innerHTML = `
      <article class="menu-v2-panel menu-admin-panel">
        <header class="menu-v2-panel-head menu-admin-panel-head">
          <label>
            Nombre del grupo
            <input type="text" value="${category.label}" data-admin-category-field="label">
          </label>
          <label>
            Descripcion del grupo
            <textarea rows="2" data-admin-category-field="description">${category.description}</textarea>
          </label>
        </header>

        <div class="menu-v2-grid menu-admin-grid">
          ${category.items
            .map(
              (item, index) => `
            <article class="menu-v2-product" data-admin-item-index="${index}">
              <figure class="menu-v2-product-media media-shell menu-admin-media" data-fallback="${item.name}">
                <img src="${item.image}" alt="${item.alt || item.name}">
                <input
                  class="menu-admin-image-input"
                  type="file"
                  accept="image/*"
                  data-admin-upload-image
                  data-admin-item-index="${index}"
                >
                <button
                  type="button"
                  class="menu-admin-image-edit"
                  data-admin-image-pick="${index}"
                  aria-label="Cambiar imagen de ${item.name}"
                  title="Cambiar imagen"
                >
                  <svg viewBox="0 0 24 24" aria-hidden="true" focusable="false">
                    <path d="M12 20h9"></path>
                    <path d="M16.5 3.5a2.12 2.12 0 0 1 3 3L7 19l-4 1 1-4 12.5-12.5z"></path>
                  </svg>
                </button>
              </figure>
              <div class="menu-v2-product-copy">
                <p class="menu-v2-kicker" contenteditable="plaintext-only" data-admin-field="tag" data-admin-item-index="${index}">${item.tag}</p>
                <h3 contenteditable="plaintext-only" data-admin-field="name" data-admin-item-index="${index}">${item.name}</h3>
                <p contenteditable="plaintext-only" data-admin-field="description" data-admin-item-index="${index}">${item.description}</p>
                <div class="menu-v2-meta">
                  <strong contenteditable="plaintext-only" data-admin-field="price" data-admin-item-index="${index}">${item.price}</strong>
                  <span contenteditable="plaintext-only" data-admin-field="badge" data-admin-item-index="${index}">${item.badge}</span>
                </div>

                <div class="menu-admin-item-tools">
                  <label class="menu-admin-toggle">
                    <input type="checkbox" ${item.essential ? "checked" : ""} data-admin-input-field="essential" data-admin-item-index="${index}">
                    <span class="menu-admin-toggle__box">
                      <span class="menu-admin-toggle__text">Imprescindible (home)</span>
                      <span class="menu-admin-toggle__check" aria-hidden="true">✓</span>
                    </span>
                  </label>
                  <button type="button" class="menu-admin-remove-item" data-admin-remove-item="${index}">Eliminar producto</button>
                </div>
              </div>
            </article>
          `
            )
            .join("")}
        </div>
      </article>
    `;
  };

  const updateImagePreview = (itemIndex, imagePath, altText) => {
    const imageNode = editorNode.querySelector(
      `[data-admin-item-index="${itemIndex}"] .menu-v2-product-media img`
    );
    const figureNode = editorNode.querySelector(`[data-admin-item-index="${itemIndex}"] .menu-v2-product-media`);
    if (!imageNode || !figureNode) {
      return;
    }
    figureNode.classList.remove("is-missing");
    imageNode.src = imagePath;
    imageNode.alt = altText || imageNode.alt;
  };

  const persistData = async () => {
    try {
      menuData = await window.MenuStore.saveData(menuData);
      isDirty = false;
      setStatus("Carta guardada en archivo (menu-data.json).", "ok");
    } catch (error) {
      const detail = getErrorMessage(error, "No se pudo guardar en archivo.");
      setStatus(`${detail}. ${getServerHint()}`, "error");
    }
  };

  initEssentialModalEvents();

  categoryListNode.addEventListener("click", (event) => {
    const target = event.target.closest("[data-admin-category]");
    if (!target) {
      return;
    }
    const categoryId = target.getAttribute("data-admin-category");
    if (!categoryId) {
      return;
    }
    activeCategoryId = categoryId;
    renderCategoryList();
    renderEditor();
    initMediaFallback(editorNode);
  });

  addItemButton.addEventListener("click", () => {
    const category = getActiveCategory();
    if (!category) {
      return;
    }
    category.items.push(createEmptyItem(category));
    renderEditor();
    initMediaFallback(editorNode);
    markDirty();
  });

  editorNode.addEventListener("keydown", (event) => {
    const editable = event.target.closest("[contenteditable]");
    if (!editable) {
      return;
    }
    if (event.key === "Enter") {
      event.preventDefault();
      editable.blur();
    }
  });

  editorNode.addEventListener("input", (event) => {
    const category = getActiveCategory();
    if (!category) {
      return;
    }

    const categoryFieldNode = event.target.closest("[data-admin-category-field]");
    if (categoryFieldNode) {
      const field = categoryFieldNode.getAttribute("data-admin-category-field");
      if (field === "label" || field === "description") {
        category[field] = categoryFieldNode.value.trim() || category[field];
        if (field === "label") {
          renderCategoryList();
        }
        markDirty();
      }
      return;
    }

    const contentNode = event.target.closest("[data-admin-field]");
    if (contentNode) {
      const field = contentNode.getAttribute("data-admin-field");
      const index = Number(contentNode.getAttribute("data-admin-item-index"));
      if (!Number.isInteger(index) || !category.items[index]) {
        return;
      }
      const nextValue = contentNode.textContent.trim();
      category.items[index][field] = nextValue || category.items[index][field];
      if (field === "name") {
        category.items[index].alt = category.items[index][field];
      }
      markDirty();
      return;
    }

    const inputFieldNode = event.target.closest("[data-admin-input-field]");
    if (inputFieldNode) {
      const field = inputFieldNode.getAttribute("data-admin-input-field");
      const index = Number(inputFieldNode.getAttribute("data-admin-item-index"));
      if (!Number.isInteger(index) || !category.items[index]) {
        return;
      }

      if (field === "essential") {
        const wantsEssential = Boolean(inputFieldNode.checked);
        const currentItem = category.items[index];
        if (wantsEssential) {
          const essentials = getEssentialEntries();
          const isAlreadyEssential = Boolean(currentItem.essential);
          if (!isAlreadyEssential && essentials.length >= 4) {
            inputFieldNode.checked = false;
            openEssentialModal(category.id, index);
            setStatus("Solo puedes tener 4 imprescindibles. Elige cuál descartar.", "warn");
            return;
          }
          currentItem.essential = true;
          markDirty();
          setStatus("Imprescindible marcado. Pulsa guardar para actualizar home.", "warn");
          return;
        }

        currentItem.essential = false;
        markDirty();
        setStatus("Imprescindible quitado. Pulsa guardar para actualizar home.", "warn");
        return;
      }
    }
  });

  editorNode.addEventListener("change", async (event) => {
    const uploadNode = event.target.closest("[data-admin-upload-image]");
    if (!uploadNode) {
      return;
    }

    const category = getActiveCategory();
    if (!category) {
      return;
    }

    const index = Number(uploadNode.getAttribute("data-admin-item-index"));
    if (!Number.isInteger(index) || !category.items[index]) {
      return;
    }

    const file = uploadNode.files?.[0];
    if (!file) {
      return;
    }

    try {
      setStatus("Subiendo imagen...", "info");
      const json = await window.MenuStore.uploadImage(
        file,
        category.items[index].id || `${category.id}-${index + 1}`
      );
      if (!json.path) {
        throw new Error("Respuesta de subida inválida");
      }

      category.items[index].image = json.path;
      category.items[index].alt = category.items[index].name;

      updateImagePreview(index, category.items[index].image, category.items[index].alt);
      markDirty();
      setStatus("Imagen subida. Pulsa guardar para persistir cambios en archivo.", "warn");
    } catch (error) {
      const detail = getErrorMessage(error, "No se pudo subir imagen.");
      setStatus(`${detail}. ${getServerHint()}`, "error");
    } finally {
      uploadNode.value = "";
    }
  });

  editorNode.addEventListener("click", (event) => {
    const imagePickNode = event.target.closest("[data-admin-image-pick]");
    if (imagePickNode) {
      const index = Number(imagePickNode.getAttribute("data-admin-image-pick"));
      if (!Number.isInteger(index)) {
        return;
      }
      const uploadInput = editorNode.querySelector(
        `[data-admin-upload-image][data-admin-item-index="${index}"]`
      );
      if (uploadInput) {
        uploadInput.click();
      }
      return;
    }

    const removeNode = event.target.closest("[data-admin-remove-item]");
    if (!removeNode) {
      return;
    }

    const index = Number(removeNode.getAttribute("data-admin-remove-item"));
    const category = getActiveCategory();
    if (!Number.isInteger(index) || !category?.items[index]) {
      return;
    }

    category.items.splice(index, 1);
    if (!category.items.length) {
      category.items.push(createEmptyItem(category));
    }

    renderEditor();
    initMediaFallback(editorNode);
    markDirty();
  });

  saveButton.addEventListener("click", async () => {
    await persistData();
  });

  exportButton.addEventListener("click", () => {
    const fileContent = JSON.stringify(menuData, null, 2);
    const blob = new Blob([fileContent], { type: "application/json" });
    const url = URL.createObjectURL(blob);
    const link = document.createElement("a");
    link.href = url;
    link.download = `titas-carta-${new Date().toISOString().slice(0, 10)}.json`;
    link.click();
    URL.revokeObjectURL(url);
    setStatus("JSON exportado.", "ok");
  });

  importInput.addEventListener("change", async (event) => {
    const file = event.target.files?.[0];
    if (!file) {
      return;
    }

    try {
      const text = await file.text();
      const parsed = JSON.parse(text);
      menuData = window.MenuStore.normalizeData(parsed);
      activeCategoryId = menuData.defaultCategoryId || menuData.categories[0].id;
      renderCategoryList();
      renderEditor();
      initMediaFallback(editorNode);
      markDirty();
      setStatus("JSON importado. Recuerda guardar cambios.", "warn");
    } catch (error) {
      setStatus("No pude importar ese archivo JSON.", "error");
    } finally {
      importInput.value = "";
    }
  });

  resetButton.addEventListener("click", async () => {
    const confirmed = window.confirm(
      "Esto restaurará la carta base y sobrescribirá tu versión guardada en archivo. ¿Quieres continuar?"
    );
    if (!confirmed) {
      return;
    }
    try {
      menuData = await window.MenuStore.resetData();
      activeCategoryId = menuData.defaultCategoryId || menuData.categories[0].id;
      renderCategoryList();
      renderEditor();
      initMediaFallback(editorNode);
      isDirty = false;
      setStatus("Carta restaurada a la versión base.", "ok");
    } catch (error) {
      const detail = getErrorMessage(error, "No se pudo restaurar la carta.");
      setStatus(`${detail}. ${getServerHint()}`, "error");
    }
  });

  window.addEventListener("beforeunload", (event) => {
    if (!isDirty) {
      return;
    }
    event.preventDefault();
    event.returnValue = "";
  });

  try {
    menuData = await window.MenuStore.loadData();
    activeCategoryId = menuData.defaultCategoryId || menuData.categories[0]?.id;
  } catch (error) {
    menuData = window.MenuStore.getDefaultData();
    activeCategoryId = menuData.defaultCategoryId || menuData.categories[0]?.id;
    setStatus("No pude leer archivo, cargué valores base.", "warn");
  }

  renderCategoryList();
  renderEditor();
  initMediaFallback(editorNode);
})();
