const menuToggle = document.querySelector("[data-menu-toggle]");
const mainNav = document.querySelector("[data-main-nav]");
const navLinks = mainNav ? mainNav.querySelectorAll("a") : [];

if (menuToggle && mainNav) {
  const openClass = "is-open";

  const setMenuState = (isOpen) => {
    mainNav.classList.toggle(openClass, isOpen);
    menuToggle.setAttribute("aria-expanded", String(isOpen));
    document.body.classList.toggle("menu-open", isOpen);
  };

  menuToggle.addEventListener("click", () => {
    const isOpen = mainNav.classList.contains(openClass);
    setMenuState(!isOpen);
  });

  navLinks.forEach((link) => {
    link.addEventListener("click", () => setMenuState(false));
  });

  document.addEventListener("keydown", (event) => {
    if (event.key === "Escape") {
      setMenuState(false);
    }
  });

  document.addEventListener("click", (event) => {
    if (window.innerWidth > 980) {
      return;
    }

    const clickedOutsideMenu = !mainNav.contains(event.target);
    const clickedOutsideButton = !menuToggle.contains(event.target);

    if (clickedOutsideMenu && clickedOutsideButton) {
      setMenuState(false);
    }
  });

  window.addEventListener("resize", () => {
    if (window.innerWidth > 980) {
      setMenuState(false);
    }
  });
}

const markMissingImage = (shell) => {
  if (!shell) {
    return;
  }
  shell.classList.add("is-missing");
};

const initMediaFallback = (root = document) => {
  const mediaShells = root.querySelectorAll(".media-shell");
  mediaShells.forEach((shell) => {
    const image = shell.querySelector("img");
    if (!image) {
      return;
    }

    if (image.complete && image.naturalWidth === 0) {
      markMissingImage(shell);
    }

    image.addEventListener("error", () => markMissingImage(shell), { once: true });
  });
};

initMediaFallback(document);

const yearNode = document.querySelector("[data-year]");
if (yearNode) {
  yearNode.textContent = new Date().getFullYear();
}

const escapeHTML = (value) =>
  String(value ?? "")
    .replaceAll("&", "&amp;")
    .replaceAll("<", "&lt;")
    .replaceAll(">", "&gt;")
    .replaceAll('"', "&quot;")
    .replaceAll("'", "&#39;");

const initMenuTabs = (
  root = document,
  { initialKey = null, syncHash = true, updateHashOnInit = false } = {}
) => {
  const menuTabs = root.querySelectorAll("[data-menu-tab]");
  const menuPanels = root.querySelectorAll("[data-menu-panel]");
  if (!menuTabs.length || !menuPanels.length) {
    return false;
  }

  const panelByKey = new Map();
  const tabByKey = new Map();
  const keyByPanelId = new Map();

  menuPanels.forEach((panel) => {
    const key = panel.getAttribute("data-menu-panel");
    if (!key) {
      return;
    }
    panelByKey.set(key, panel);
    if (panel.id) {
      keyByPanelId.set(panel.id, key);
    }
  });

  menuTabs.forEach((tab) => {
    const key = tab.getAttribute("data-menu-tab");
    if (key) {
      tabByKey.set(key, tab);
    }
  });

  const activateMenuTab = (key, shouldSyncHash = true) => {
    if (!panelByKey.has(key) || !tabByKey.has(key)) {
      return;
    }

    menuTabs.forEach((tab) => {
      const isActive = tab.getAttribute("data-menu-tab") === key;
      tab.classList.toggle("is-active", isActive);
      tab.setAttribute("aria-selected", String(isActive));
      tab.setAttribute("tabindex", isActive ? "0" : "-1");
    });

    menuPanels.forEach((panel) => {
      const isActive = panel.getAttribute("data-menu-panel") === key;
      panel.classList.toggle("is-active", isActive);
      panel.hidden = !isActive;
    });

    if (!syncHash || !shouldSyncHash) {
      return;
    }

    const activePanel = panelByKey.get(key);
    if (activePanel && activePanel.id) {
      history.replaceState(null, "", `#${activePanel.id}`);
    }
  };

  menuTabs.forEach((tab) => {
    tab.addEventListener("click", () => {
      const key = tab.getAttribute("data-menu-tab");
      if (key) {
        activateMenuTab(key, true);
      }
    });
  });

  const activateFromHash = () => {
    const rawHash = window.location.hash.replace("#", "");
    const keyFromHash = keyByPanelId.get(rawHash);
    if (keyFromHash) {
      activateMenuTab(keyFromHash, false);
    }
  };

  const activeTab = root.querySelector("[data-menu-tab].is-active");
  const fallbackKey = activeTab ? activeTab.getAttribute("data-menu-tab") : null;
  const firstKey = menuTabs[0]?.getAttribute("data-menu-tab") || null;
  const resolvedInitialKey = initialKey || fallbackKey || firstKey;

  if (resolvedInitialKey) {
    activateMenuTab(resolvedInitialKey, updateHashOnInit);
  }

  if (syncHash) {
    activateFromHash();
    window.addEventListener("hashchange", activateFromHash);
  }

  return true;
};

const renderPublicMenuFromStore = async () => {
  const menuPage = document.querySelector(".menu-page-v2:not(.menu-admin-page)");
  if (!menuPage || !window.MenuStore) {
    return false;
  }

  const tabsMount = menuPage.querySelector("[data-menu-tabs]");
  const panelsMount = menuPage.querySelector("[data-menu-panels]");
  if (!tabsMount || !panelsMount) {
    return false;
  }

  let data = null;
  try {
    data = await window.MenuStore.loadData();
  } catch (error) {
    data = window.MenuStore.getDefaultData();
  }

  if (!data.categories?.length) {
    return false;
  }

  const eyebrowNode = menuPage.querySelector("[data-menu-brand-eyebrow]");
  const titleNode = menuPage.querySelector("[data-menu-brand-title]");
  const descriptionNode = menuPage.querySelector("[data-menu-brand-description]");

  if (eyebrowNode) eyebrowNode.textContent = data.brand.eyebrow;
  if (titleNode) titleNode.textContent = data.brand.title;
  if (descriptionNode) descriptionNode.textContent = data.brand.description;

  tabsMount.innerHTML = data.categories
    .map(
      (category) => `
      <button
        id="tab-${escapeHTML(category.id)}"
        class="menu-v2-tab"
        type="button"
        role="tab"
        aria-selected="false"
        aria-controls="menu-${escapeHTML(category.id)}"
        data-menu-tab="${escapeHTML(category.id)}"
      >${escapeHTML(category.label)}</button>
    `
    )
    .join("");

  panelsMount.innerHTML = data.categories
    .map((category) => {
      const itemsHTML = category.items
        .map((item) => {
          const featuredClass = item.featured ? " menu-v2-product-featured" : "";
          return `
          <article class="menu-v2-product${featuredClass}">
            <figure class="menu-v2-product-media media-shell" data-fallback="${escapeHTML(item.name)}">
              <img src="${escapeHTML(item.image)}" alt="${escapeHTML(item.alt)}">
            </figure>
            <div class="menu-v2-product-copy">
              <p class="menu-v2-kicker">${escapeHTML(item.tag)}</p>
              <h3>${escapeHTML(item.name)}</h3>
              <p>${escapeHTML(item.description)}</p>
              <div class="menu-v2-meta">
                <strong>${escapeHTML(item.price)}</strong>
                <span>${escapeHTML(item.badge)}</span>
              </div>
            </div>
          </article>
        `;
        })
        .join("");

      return `
      <article
        id="menu-${escapeHTML(category.id)}"
        class="menu-v2-panel"
        role="tabpanel"
        aria-labelledby="tab-${escapeHTML(category.id)}"
        data-menu-panel="${escapeHTML(category.id)}"
        hidden
      >
        <header class="menu-v2-panel-head">
          <h2>${escapeHTML(category.label)}</h2>
          <p>${escapeHTML(category.description)}</p>
        </header>
        <div class="menu-v2-grid">
          ${itemsHTML}
        </div>
      </article>
    `;
    })
    .join("");

  initMediaFallback(menuPage);

  const hashId = window.location.hash.replace("#", "");
  const hashCategoryId = hashId.startsWith("menu-") ? hashId.slice(5) : "";
  const hasHashCategory = data.categories.some((category) => category.id === hashCategoryId);
  const initialKey = hasHashCategory
    ? hashCategoryId
    : data.defaultCategoryId || data.categories[0].id;

  initMenuTabs(menuPage, {
    initialKey,
    syncHash: true,
    updateHashOnInit: false
  });

  return true;
};

void (async () => {
  const wasMenuRendered = await renderPublicMenuFromStore();
  if (!wasMenuRendered) {
    initMenuTabs(document, { syncHash: true });
  }
})();
