(function () {
  const NAV_ENDPOINT = "/navigation/sidebar";
  const SIDEBAR_SELECTOR = ".sidebar-nav";
  const DATA_SOURCE_ATTR = "navigationSource";
  const ROLE_ATTR = "navigationRoles";

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

  function isActivePath(pathname, matchPrefix) {
    if (!matchPrefix) {
      return false;
    }
    if (matchPrefix === "/") {
      return pathname === "/";
    }
    return pathname.startsWith(matchPrefix);
  }

  function createAnchor({
    href,
    label,
    matchPrefix,
    tooltip,
    isExternal,
    isActive,
    className,
  }) {
    const anchor = document.createElement("a");
    anchor.href = href;
    anchor.className = className + (isActive ? " is-active" : "");
    anchor.dataset.matchPrefix = matchPrefix || href;
    if (tooltip) {
      anchor.title = tooltip;
    }
    if (isExternal) {
      anchor.target = "_blank";
      anchor.rel = "noopener noreferrer";
      anchor.classList.add("is-external");
    }
    anchor.textContent = label;
    return anchor;
  }

  function buildLinkBlock(link, pathname) {
    if (!link || !link.href) {
      return null;
    }
    const matchPrefix = link.match_prefix || link.matchPrefix || link.href;
    const isActive = isActivePath(pathname, matchPrefix);

    const block = document.createElement("div");
    block.className = "sidebar-link-block";
    if (typeof link.id === "number") {
      block.dataset.linkId = String(link.id);
    }

    const anchor = createAnchor({
      href: link.href,
      label: link.label,
      matchPrefix,
      tooltip: link.tooltip,
      isExternal: Boolean(link.is_external ?? link.isExternal),
      isActive,
      className: "sidebar-link",
    });
    block.appendChild(anchor);

    const children = Array.isArray(link.children) ? link.children : [];
    if (children.length > 0) {
      const container = document.createElement("div");
      container.className = "sidebar-sublinks";
      for (const child of children) {
        if (!child || !child.href) {
          continue;
        }
        const childMatch =
          child.match_prefix || child.matchPrefix || child.href;
        const childActive = isActivePath(pathname, childMatch);
        const childAnchor = createAnchor({
          href: child.href,
          label: child.label,
          matchPrefix: childMatch,
          tooltip: child.tooltip,
          isExternal: Boolean(child.is_external ?? child.isExternal),
          isActive: childActive,
          className: "sidebar-sublink",
        });
        container.appendChild(childAnchor);
      }
      if (container.children.length > 0) {
        block.appendChild(container);
      }
    }

    return block;
  }

  function buildGroupSection(group, pathname) {
    if (!group) {
      return null;
    }
    const links = Array.isArray(group.links) ? group.links : [];
    if (links.length === 0) {
      return null;
    }

    const section = document.createElement("div");
    section.className = "sidebar-section";
    if (typeof group.id === "number") {
      section.dataset.groupId = String(group.id);
    }

    const label = document.createElement("div");
    label.className = "sidebar-section-label";
    label.textContent = group.label;
    section.appendChild(label);

    const linksContainer = document.createElement("div");
    linksContainer.className = "sidebar-section-links";

    for (const link of links) {
      const block = buildLinkBlock(link, pathname);
      if (block) {
        linksContainer.appendChild(block);
      }
    }

    if (linksContainer.children.length === 0) {
      return null;
    }

    section.appendChild(linksContainer);
    return section;
  }

  function buildEmptyState() {
    const section = document.createElement("div");
    section.className = "sidebar-section sidebar-empty-state";

    const label = document.createElement("div");
    label.className = "sidebar-section-label";
    label.textContent = "Navigation";
    section.appendChild(label);

    const copyWrapper = document.createElement("div");
    copyWrapper.className = "sidebar-section-links";

    const copy = document.createElement("p");
    copy.className = "sidebar-empty-copy";
    copy.textContent = "Navigation is unavailable.";
    copyWrapper.appendChild(copy);

    section.appendChild(copyWrapper);
    return section;
  }

  function renderSidebar(navContainer, payload) {
    const pathname = window.location.pathname;
    const groups = Array.isArray(payload?.groups) ? payload.groups : [];
    navContainer.replaceChildren();

    const rendered = [];
    for (const group of groups) {
      const section = buildGroupSection(group, pathname);
      if (section) {
        rendered.push(section);
      }
    }

    if (rendered.length === 0) {
      navContainer.appendChild(buildEmptyState());
      navContainer.dataset[DATA_SOURCE_ATTR] = "client-empty";
      delete navContainer.dataset[ROLE_ATTR];
      return;
    }

    for (const section of rendered) {
      navContainer.appendChild(section);
    }

    navContainer.dataset[DATA_SOURCE_ATTR] = "client";
    const roles = Array.isArray(payload?.roles) ? payload.roles : [];
    if (roles.length > 0) {
      navContainer.dataset[ROLE_ATTR] = roles.join(",");
    } else {
      delete navContainer.dataset[ROLE_ATTR];
    }
  }

  async function hydrateSidebar(navContainer) {
    try {
      const response = await fetch(NAV_ENDPOINT, {
        method: "GET",
        credentials: "include",
        headers: {
          Accept: "application/json",
        },
      });

      if (!response.ok) {
        if (response.status !== 401 && response.status !== 403) {
          console.warn(
            "Navigation sidebar hydration failed with status",
            response.status
          );
        }
        return;
      }

      const payload = await response.json();
      renderSidebar(navContainer, payload);
    } catch (error) {
      console.warn("Navigation sidebar hydration failed", error);
    }
  }

  onReady(() => {
    const navContainer = document.querySelector(SIDEBAR_SELECTOR);
    if (!navContainer) {
      return;
    }
    hydrateSidebar(navContainer);
  });
})();
