(function attachMenuStore() {
  const DEFAULT_MENU_DATA = {
    version: 1,
    brand: {
      eyebrow: "CARTA VISUAL",
      title: "Elige tu antojo y descubre la carta",
      description:
        "Selecciona una categoría para ver sus productos. Diseño pensado para móvil, con fotos grandes y foco en lo que apetece pedir."
    },
    defaultCategoryId: "burgers",
    categories: [
      {
        id: "brunch",
        label: "Brunch",
        description: "Opciones suaves, sabrosas y perfectas para cualquier hora.",
        items: [
          {
            id: "french-toast",
            tag: "Brunch favorito",
            name: "French Toast Tita's",
            description: "Pan brioche, crema suave y frutos rojos.",
            price: "8,80 €",
            badge: "Top mañanas",
            image: "./assets/milkshake.webp",
            alt: "French toast de la carta",
            featured: false
          },
          {
            id: "huevos-benedict",
            tag: "Con mucho cuerpo",
            name: "Huevos Benedict",
            description: "Pan artesano, bacon crispy y salsa holandesa.",
            price: "10,50 €",
            badge: "Brunch deluxe",
            image: "./assets/burger-plate.webp",
            alt: "Huevos benedict de la carta",
            featured: false
          }
        ]
      },
      {
        id: "burgers",
        label: "Burgers",
        description: "Smash burgers con presencia, queso fundido y personalidad.",
        items: [
          {
            id: "titas-smash",
            tag: "Nuestra estrella",
            name: "Tita's Smash Burger",
            description: "Doble carne smash, cheddar, cebolla caramelizada y salsa de la casa.",
            price: "12,90 €",
            badge: "Favorita del local",
            image: "./assets/burger-plate.webp",
            alt: "Tita's Smash Burger",
            featured: true
          },
          {
            id: "classic-cheese",
            tag: "Cheese lover",
            name: "Classic Cheese",
            description: "Carne smash, cheddar maduro, pepinillo y salsa burger.",
            price: "10,90 €",
            badge: "Muy cremosa",
            image: "./assets/burger-plate.webp",
            alt: "Classic Cheese Burger",
            featured: false
          },
          {
            id: "veggie-garden",
            tag: "Opción veggie",
            name: "Veggie Garden Burger",
            description: "Base vegetal, hummus rosa y brotes tiernos.",
            price: "10,50 €",
            badge: "Fresca y ligera",
            image: "./assets/burger-plate.webp",
            alt: "Veggie Garden Burger",
            featured: false
          }
        ]
      },
      {
        id: "shakes",
        label: "Shakes & Coffee",
        description: "Batidos y café para acompañar cualquier plan bonito.",
        items: [
          {
            id: "kinder-bueno-shake",
            tag: "Best seller",
            name: "Batido Kinder Bueno",
            description: "Helado cremoso, nata y sirope de avellana.",
            price: "6,50 €",
            badge: "Irresistible",
            image: "./assets/milkshake.webp",
            alt: "Batido Kinder Bueno",
            featured: true
          },
          {
            id: "strawberry-bliss",
            tag: "Muy suave",
            name: "Strawberry Bliss",
            description: "Fresa, vainilla suave y topping de nata.",
            price: "6,20 €",
            badge: "Muy instagrameable",
            image: "./assets/milkshake.webp",
            alt: "Batido Strawberry Bliss",
            featured: false
          }
        ]
      },
      {
        id: "dulce",
        label: "Dulce",
        description: "Caprichos para terminar redondo o acompañar tu café.",
        items: [
          {
            id: "carrot-cake",
            tag: "Recomendado",
            name: "Carrot Cake",
            description: "Bizcocho especiado con crema suave de queso.",
            price: "4,50 €",
            badge: "Hecho en casa",
            image: "./assets/milkshake.webp",
            alt: "Porción de carrot cake",
            featured: false
          },
          {
            id: "brownie-tibio",
            tag: "Chocolate lover",
            name: "Brownie Tibio",
            description: "Chocolate intenso, nuez y toque de sal marina.",
            price: "4,20 €",
            badge: "Textura brutal",
            image: "./assets/burger-plate.webp",
            alt: "Brownie tibio",
            featured: false
          }
        ]
      }
    ]
  };

  const clone = (value) => JSON.parse(JSON.stringify(value));

  const safeText = (value, fallback) => {
    if (typeof value !== "string") {
      return fallback;
    }
    const trimmed = value.trim();
    return trimmed.length ? trimmed : fallback;
  };

  const normalizeItem = (item, fallbackItem) => ({
    id: safeText(item?.id, fallbackItem.id),
    tag: safeText(item?.tag, fallbackItem.tag),
    name: safeText(item?.name, fallbackItem.name),
    description: safeText(item?.description, fallbackItem.description),
    price: safeText(item?.price, fallbackItem.price),
    badge: safeText(item?.badge, fallbackItem.badge),
    image: safeText(item?.image, fallbackItem.image),
    alt: safeText(item?.alt, fallbackItem.alt),
    featured: Boolean(item?.featured)
  });

  const normalizeCategory = (category, fallbackCategory) => {
    const sourceItems = Array.isArray(category?.items) ? category.items : [];
    const fallbackItems = Array.isArray(fallbackCategory.items) ? fallbackCategory.items : [];
    const normalizedItems = sourceItems.length
      ? sourceItems.map((entry, index) => normalizeItem(entry, fallbackItems[index] || fallbackItems[0]))
      : fallbackItems.map((entry) => normalizeItem(entry, entry));

    return {
      id: safeText(category?.id, fallbackCategory.id),
      label: safeText(category?.label, fallbackCategory.label),
      description: safeText(category?.description, fallbackCategory.description),
      items: normalizedItems
    };
  };

  const normalizeData = (candidate) => {
    const fallback = DEFAULT_MENU_DATA;
    const source = candidate && typeof candidate === "object" ? candidate : {};
    const sourceCategories = Array.isArray(source.categories) ? source.categories : [];

    const categories = fallback.categories.map((fallbackCategory) => {
      const match = sourceCategories.find((entry) => entry?.id === fallbackCategory.id);
      if (match) {
        return normalizeCategory(match, fallbackCategory);
      }
      return normalizeCategory(fallbackCategory, fallbackCategory);
    });

    const defaultCategoryId = safeText(source.defaultCategoryId, fallback.defaultCategoryId);
    const hasDefault = categories.some((entry) => entry.id === defaultCategoryId);

    return {
      version: 1,
      brand: {
        eyebrow: safeText(source.brand?.eyebrow, fallback.brand.eyebrow),
        title: safeText(source.brand?.title, fallback.brand.title),
        description: safeText(source.brand?.description, fallback.brand.description)
      },
      defaultCategoryId: hasDefault ? defaultCategoryId : categories[0].id,
      categories
    };
  };

  let cachedData = null;

  const MENU_READ_SOURCES = ["./api/menu.php", "/api/menu", "./menu-data.json"];
  const MENU_WRITE_TARGETS = ["./api/menu.php", "/api/menu"];
  const IMAGE_UPLOAD_TARGETS = ["./api/upload.php", "/api/upload"];

  const parseJSON = async (response) => {
    const text = await response.text();
    if (!text.trim()) {
      return null;
    }
    return JSON.parse(text);
  };

  const fetchMenuData = async () => {
    for (const source of MENU_READ_SOURCES) {
      try {
        const response = await fetch(source, { cache: "no-store" });
        if (!response.ok) {
          continue;
        }
        const parsed = await parseJSON(response);
        if (!parsed) {
          continue;
        }
        return normalizeData(parsed);
      } catch (error) {
        continue;
      }
    }

    return clone(DEFAULT_MENU_DATA);
  };

  const saveMenuDataToFile = async (normalizedData) => {
    let lastError = null;
    for (const target of MENU_WRITE_TARGETS) {
      try {
        const response = await fetch(target, {
          method: "POST",
          headers: {
            "Content-Type": "application/json"
          },
          body: JSON.stringify(normalizedData)
        });

        if (!response.ok) {
          const reason = await response.text();
          lastError = new Error(reason || "No se pudo guardar en archivo.");
          continue;
        }

        return;
      } catch (error) {
        lastError = error;
      }
    }

    throw lastError || new Error("No se pudo guardar en archivo.");
  };

  const uploadImageToServer = async (file, itemId = "item") => {
    let lastError = null;

    for (const target of IMAGE_UPLOAD_TARGETS) {
      try {
        const payload = new FormData();
        payload.append("image", file);
        payload.append("itemId", itemId);

        const response = await fetch(target, {
          method: "POST",
          body: payload
        });

        if (!response.ok) {
          const reason = await response.text();
          lastError = new Error(reason || "No se pudo subir imagen.");
          continue;
        }

        const json = await response.json();
        if (!json.path) {
          lastError = new Error("Respuesta de subida inválida.");
          continue;
        }

        return json;
      } catch (error) {
        lastError = error;
      }
    }

    throw lastError || new Error("No se pudo subir imagen.");
  };

  const MenuStore = {
    getDefaultData() {
      return clone(DEFAULT_MENU_DATA);
    },
    normalizeData,
    async loadData({ force = false } = {}) {
      if (!force && cachedData) {
        return clone(cachedData);
      }
      cachedData = await fetchMenuData();
      return clone(cachedData);
    },
    async saveData(data) {
      const normalized = normalizeData(data);
      await saveMenuDataToFile(normalized);
      cachedData = normalized;
      return clone(normalized);
    },
    async resetData() {
      const resetData = clone(DEFAULT_MENU_DATA);
      await saveMenuDataToFile(resetData);
      cachedData = resetData;
      return clone(resetData);
    },
    async uploadImage(file, itemId) {
      return uploadImageToServer(file, itemId);
    }
  };

  window.MenuStore = MenuStore;
})();
