/* ========================================================================== 
   VANTA NOIR / INTERACTION LAYER
   Framework-free modules for navigation, lookbook signals, cart state,
   reveal-on-scroll, and the newsletter front-end success state.
   ========================================================================== */

(() => {
  "use strict";

  const SELECTORS = {
    body: document.body,
    header: document.querySelector("[data-header]"),
    menuToggle: document.querySelector("[data-menu-toggle]"),
    menu: document.querySelector("#mobile-menu"),
    menuScrim: document.querySelector("[data-menu-scrim]"),
    menuClose: document.querySelector("[data-menu-close]"),
    menuLinks: [...document.querySelectorAll("[data-menu-link]")],
    cart: document.querySelector("#cart-drawer"),
    cartScrim: document.querySelector("[data-cart-scrim]"),
    cartOpeners: [...document.querySelectorAll("[data-cart-open]")],
    cartClosers: [...document.querySelectorAll("[data-cart-close]")],
    cartItems: document.querySelector("[data-cart-items]"),
    cartCountTargets: [...document.querySelectorAll("[data-cart-count]")],
    cartSubtotal: document.querySelector("[data-cart-subtotal]"),
    checkout: document.querySelector("[data-checkout]"),
    cartStatus: document.querySelector("[data-cart-status]"),
    liveRegion: document.querySelector("[data-live-region]"),
    revealItems: [...document.querySelectorAll("[data-reveal]")],
    newsletterForm: document.querySelector("[data-newsletter-form]"),
    newsletterStatus: document.querySelector("[data-newsletter-status]")
  };

  const STORAGE_KEY = "vanta-noir-cart-v1";
  const currency = new Intl.NumberFormat("en-NG", {
    style: "currency",
    currency: "NGN",
    maximumFractionDigits: 0
  });

  const state = {
    cart: loadCart(),
    menuOpen: false,
    cartOpen: false,
    lastFocusedElement: null,
    activePanel: null
  };

  /* ------------------------------- Helpers ----------------------------- */

  function formatCurrency(value) {
    return currency.format(Number(value) || 0).replace(/\s/g, " ");
  }

  function announce(message) {
    if (!SELECTORS.liveRegion) return;
    SELECTORS.liveRegion.textContent = "";
    window.setTimeout(() => {
      SELECTORS.liveRegion.textContent = message;
    }, 20);
  }

  function setPanelVisibility(panel, isOpen) {
    if (!panel) return;
    panel.setAttribute("aria-hidden", String(!isOpen));
    panel.classList.toggle("is-open", isOpen);
    panel.toggleAttribute("inert", !isOpen);
  }

  function lockBody(isLocked) {
    SELECTORS.body.classList.toggle("menu-open", isLocked && state.menuOpen);
    SELECTORS.body.classList.toggle("cart-open", isLocked && state.cartOpen);
  }

  function getFocusableElements(container) {
    if (!container) return [];
    return [...container.querySelectorAll("a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex=\"-1\"])")];
  }

  function trapFocus(event, container) {
    if (event.key !== "Tab" || !container) return;
    const focusable = getFocusableElements(container);
    if (!focusable.length) return;

    const first = focusable[0];
    const last = focusable[focusable.length - 1];

    if (event.shiftKey && document.activeElement === first) {
      event.preventDefault();
      last.focus();
    } else if (!event.shiftKey && document.activeElement === last) {
      event.preventDefault();
      first.focus();
    }
  }

  /* --------------------------- Mobile menu ----------------------------- */

  function openMenu() {
    if (!SELECTORS.menu || state.menuOpen) return;
    closeCart({ restoreFocus: false });
    state.lastFocusedElement = document.activeElement;
    state.menuOpen = true;
    SELECTORS.menuToggle?.setAttribute("aria-expanded", "true");
    SELECTORS.menuToggle?.setAttribute("aria-label", "Close menu");
    setPanelVisibility(SELECTORS.menu, true);
    SELECTORS.menuScrim?.classList.add("is-visible");
    SELECTORS.menuScrim?.setAttribute("aria-hidden", "false");
    lockBody(true);
    window.setTimeout(() => SELECTORS.menuClose?.focus(), 80);
  }

  function closeMenu({ restoreFocus = true } = {}) {
    if (!SELECTORS.menu || !state.menuOpen) return;
    state.menuOpen = false;
    SELECTORS.menuToggle?.setAttribute("aria-expanded", "false");
    SELECTORS.menuToggle?.setAttribute("aria-label", "Open menu");
    setPanelVisibility(SELECTORS.menu, false);
    SELECTORS.menuScrim?.classList.remove("is-visible");
    SELECTORS.menuScrim?.setAttribute("aria-hidden", "true");
    lockBody(false);

    if (restoreFocus && state.lastFocusedElement instanceof HTMLElement) {
      state.lastFocusedElement.focus();
    }
    state.lastFocusedElement = null;
  }

  function initMenu() {
    SELECTORS.menuToggle?.addEventListener("click", () => {
      if (state.menuOpen) {
        closeMenu();
      } else {
        openMenu();
      }
    });
    SELECTORS.menuClose?.addEventListener("click", () => closeMenu());
    SELECTORS.menuScrim?.addEventListener("click", () => closeMenu());
    SELECTORS.menuLinks.forEach((link) => link.addEventListener("click", () => closeMenu({ restoreFocus: false })));
  }

  /* ---------------------------- Cart drawer ---------------------------- */

  function openCart() {
    if (!SELECTORS.cart || state.cartOpen) return;
    closeMenu({ restoreFocus: false });
    state.lastFocusedElement = document.activeElement;
    state.cartOpen = true;
    SELECTORS.cartOpeners.forEach((button) => button.setAttribute("aria-expanded", "true"));
    setPanelVisibility(SELECTORS.cart, true);
    SELECTORS.cartScrim?.classList.add("is-visible");
    SELECTORS.cartScrim?.setAttribute("aria-hidden", "false");
    lockBody(true);
    window.setTimeout(() => SELECTORS.cart?.focus(), 80);
  }

  function closeCart({ restoreFocus = true } = {}) {
    if (!SELECTORS.cart || !state.cartOpen) return;
    state.cartOpen = false;
    SELECTORS.cartOpeners.forEach((button) => button.setAttribute("aria-expanded", "false"));
    setPanelVisibility(SELECTORS.cart, false);
    SELECTORS.cartScrim?.classList.remove("is-visible");
    SELECTORS.cartScrim?.setAttribute("aria-hidden", "true");
    lockBody(false);

    if (restoreFocus && state.lastFocusedElement instanceof HTMLElement) {
      state.lastFocusedElement.focus();
    }
    state.lastFocusedElement = null;
  }

  function initCartDrawer() {
    SELECTORS.cartOpeners.forEach((button) => button.addEventListener("click", openCart));
    SELECTORS.cartClosers.forEach((button) => button.addEventListener("click", () => closeCart({ restoreFocus: false })));
    SELECTORS.cartScrim?.addEventListener("click", () => closeCart());
  }

  /* ---------------------------- Lookbook ------------------------------- */

  function closeAllHotspots(except = null) {
    document.querySelectorAll(".hotspot-wrap.is-open").forEach((wrapper) => {
      if (wrapper === except) return;
      wrapper.classList.remove("is-open");
      wrapper.querySelector("[data-hotspot]")?.setAttribute("aria-expanded", "false");
      wrapper.querySelector(".spec-card")?.setAttribute("aria-hidden", "true");
    });
  }

  function toggleHotspot(button) {
    const wrapper = button.closest(".hotspot-wrap");
    const card = wrapper?.querySelector(".spec-card");
    if (!wrapper || !card) return;

    const willOpen = !wrapper.classList.contains("is-open");
    closeAllHotspots(wrapper);
    wrapper.classList.toggle("is-open", willOpen);
    button.setAttribute("aria-expanded", String(willOpen));
    card.setAttribute("aria-hidden", String(!willOpen));
    if (willOpen) state.activePanel = card;
    else state.activePanel = null;
  }

  function initHotspots() {
    document.querySelectorAll("[data-hotspot]").forEach((button) => {
      button.addEventListener("click", (event) => {
        event.stopPropagation();
        toggleHotspot(button);
      });
    });

    document.addEventListener("click", (event) => {
      if (!event.target.closest(".hotspot-wrap")) {
        closeAllHotspots();
        state.activePanel = null;
      }
    });
  }

  /* ------------------------------ Cart state --------------------------- */

  function loadCart() {
    try {
      const saved = JSON.parse(window.localStorage.getItem(STORAGE_KEY) || "[]");
      if (!Array.isArray(saved)) return [];
      return saved.filter((item) => item && item.id && item.name && Number(item.price) >= 0 && Number(item.quantity) > 0);
    } catch {
      return [];
    }
  }

  function saveCart() {
    try {
      window.localStorage.setItem(STORAGE_KEY, JSON.stringify(state.cart));
    } catch {
      // Storage can be unavailable in private browsing; the in-memory cart still works.
    }
  }

  function productFromCard(card) {
    if (!card) return null;
    const size = card.querySelector("[data-product-size]")?.value || "M";
    return {
      id: card.dataset.product,
      name: card.dataset.productName,
      price: Number(card.dataset.productPrice),
      color: card.dataset.productColor,
      image: card.dataset.productImage,
      size,
      quantity: 1
    };
  }

  function addToCart(product) {
    if (!product?.id) return;
    const existing = state.cart.find((item) => item.id === product.id && item.size === product.size);
    if (existing) {
      existing.quantity += 1;
    } else {
      state.cart.push(product);
    }
    saveCart();
    renderCart();
    announce(`${product.name}, size ${product.size}, added to your bag.`);
    openCart();
  }

  function updateQuantity(id, size, delta) {
    const item = state.cart.find((cartItem) => cartItem.id === id && cartItem.size === size);
    if (!item) return;
    item.quantity += delta;
    if (item.quantity <= 0) {
      state.cart = state.cart.filter((cartItem) => !(cartItem.id === id && cartItem.size === size));
    }
    saveCart();
    renderCart();
  }

  function removeFromCart(id, size) {
    const item = state.cart.find((cartItem) => cartItem.id === id && cartItem.size === size);
    state.cart = state.cart.filter((cartItem) => !(cartItem.id === id && cartItem.size === size));
    saveCart();
    renderCart();
    if (item) announce(`${item.name} removed from your bag.`);
  }

  function createCartLine(item) {
    const line = document.createElement("article");
    line.className = "cart-line";
    line.dataset.cartId = item.id;
    line.dataset.cartSize = item.size;

    const image = document.createElement("img");
    image.className = "cart-line__image";
    image.src = item.image;
    image.alt = `${item.name}, ${item.color}`;
    image.loading = "lazy";

    const content = document.createElement("div");
    content.className = "cart-line__content";

    const code = document.createElement("span");
    code.className = "cart-line__code";
    code.textContent = item.id.replace("vn-", "VN—").replaceAll("-", " ").toUpperCase();

    const title = document.createElement("h3");
    title.textContent = item.name;

    const meta = document.createElement("span");
    meta.className = "cart-line__meta";
    meta.textContent = `${item.color} / Size ${item.size}`;

    const bottom = document.createElement("div");
    bottom.className = "cart-line__bottom";

    const quantity = document.createElement("div");
    quantity.className = "cart-quantity";
    quantity.setAttribute("aria-label", `Quantity for ${item.name}`);

    const minus = document.createElement("button");
    minus.type = "button";
    minus.dataset.cartAction = "decrease";
    minus.dataset.cartId = item.id;
    minus.dataset.cartSize = item.size;
    minus.setAttribute("aria-label", `Decrease ${item.name} quantity`);
    minus.textContent = "−";

    const count = document.createElement("span");
    count.textContent = String(item.quantity);
    count.setAttribute("aria-live", "polite");

    const plus = document.createElement("button");
    plus.type = "button";
    plus.dataset.cartAction = "increase";
    plus.dataset.cartId = item.id;
    plus.dataset.cartSize = item.size;
    plus.setAttribute("aria-label", `Increase ${item.name} quantity`);
    plus.textContent = "+";

    quantity.append(minus, count, plus);
    bottom.append(quantity);

    const price = document.createElement("span");
    price.className = "cart-line__price";
    price.textContent = formatCurrency(item.price * item.quantity);

    const remove = document.createElement("button");
    remove.type = "button";
    remove.className = "cart-line__remove";
    remove.dataset.cartAction = "remove";
    remove.dataset.cartId = item.id;
    remove.dataset.cartSize = item.size;
    remove.textContent = "Remove";

    content.append(code, title, meta, bottom);
    line.append(image, content, price, remove);
    return line;
  }

  function renderCart() {
    const totalQuantity = state.cart.reduce((total, item) => total + item.quantity, 0);
    const subtotal = state.cart.reduce((total, item) => total + item.price * item.quantity, 0);

    SELECTORS.cartCountTargets.forEach((target) => {
      target.textContent = String(totalQuantity);
    });
    if (SELECTORS.cartSubtotal) SELECTORS.cartSubtotal.textContent = formatCurrency(subtotal);
    if (SELECTORS.checkout) SELECTORS.checkout.disabled = state.cart.length === 0;

    if (!SELECTORS.cartItems) return;
    SELECTORS.cartItems.replaceChildren();

    if (!state.cart.length) {
      const empty = document.createElement("div");
      empty.className = "cart-empty";
      empty.innerHTML = `<span class="cart-empty__index">00</span><h3>Your bag is quiet.</h3><p>Add a piece from the current system and it will appear here.</p><a class="text-link text-link--small" href="#shop" data-cart-close><span>Browse system</span><span aria-hidden="true">↗</span></a>`;
      SELECTORS.cartItems.append(empty);
      empty.querySelector("[data-cart-close]")?.addEventListener("click", () => closeCart({ restoreFocus: false }));
      return;
    }

    const fragment = document.createDocumentFragment();
    state.cart.forEach((item) => fragment.append(createCartLine(item)));
    SELECTORS.cartItems.append(fragment);
  }

  function initCartEvents() {
    document.addEventListener("click", (event) => {
      const addButton = event.target.closest("[data-add-to-cart]");
      if (addButton) {
        event.preventDefault();
        addToCart(productFromCard(addButton.closest("[data-product]")));
        return;
      }

      const actionButton = event.target.closest("[data-cart-action]");
      if (!actionButton) return;
      const { cartAction, cartId, cartSize } = actionButton.dataset;
      if (cartAction === "increase") updateQuantity(cartId, cartSize, 1);
      if (cartAction === "decrease") updateQuantity(cartId, cartSize, -1);
      if (cartAction === "remove") removeFromCart(cartId, cartSize);
    });

    SELECTORS.checkout?.addEventListener("click", () => {
      if (!state.cart.length) return;
      if (SELECTORS.cartStatus) SELECTORS.cartStatus.textContent = "Checkout endpoint ready for payment integration.";
      announce("Checkout endpoint ready for payment integration.");
    });
  }

  /* -------------------------- Reveal observer -------------------------- */

  function initRevealObserver() {
    if (!("IntersectionObserver" in window)) {
      SELECTORS.revealItems.forEach((item) => item.classList.add("is-visible"));
      return;
    }

    const observer = new IntersectionObserver(
      (entries, revealObserver) => {
        entries.forEach((entry) => {
          if (!entry.isIntersecting) return;
          entry.target.classList.add("is-visible");
          revealObserver.unobserve(entry.target);
        });
      },
      { threshold: 0.13, rootMargin: "0px 0px -8% 0px" }
    );

    SELECTORS.revealItems.forEach((item) => observer.observe(item));
  }

  /* --------------------------- Newsletter ------------------------------ */

  function initNewsletter() {
    SELECTORS.newsletterForm?.addEventListener("submit", (event) => {
      event.preventDefault();
      const email = new FormData(event.currentTarget).get("email");
      if (!email) return;
      if (SELECTORS.newsletterStatus) SELECTORS.newsletterStatus.textContent = "Signal received. Welcome to the system.";
      event.currentTarget.reset();
      announce("Signal received. Welcome to the system.");
    });
  }

  /* -------------------------- Global keyboard -------------------------- */

  function initGlobalKeyboard() {
    document.addEventListener("keydown", (event) => {
      if (event.key === "Escape") {
        closeMenu();
        closeCart();
        closeAllHotspots();
        state.activePanel = null;
      }
      if (state.menuOpen) trapFocus(event, SELECTORS.menu);
      if (state.cartOpen) trapFocus(event, SELECTORS.cart);
    });
  }

  /* -------------------------- Header state ----------------------------- */

  function initHeaderState() {
    if (!SELECTORS.header) return;
    const updateHeader = () => SELECTORS.header.classList.toggle("is-scrolled", window.scrollY > 18);
    updateHeader();
    window.addEventListener("scroll", updateHeader, { passive: true });
  }

  function init() {
    initMenu();
    initCartDrawer();
    initHotspots();
    initCartEvents();
    initRevealObserver();
    initNewsletter();
    initGlobalKeyboard();
    initHeaderState();
    renderCart();
  }

  if (document.readyState === "loading") {
    document.addEventListener("DOMContentLoaded", init, { once: true });
  } else {
    init();
  }
})();
