(function (global) {
  const app = (global.EpicrisisApp = global.EpicrisisApp || {});
  const controllers = new WeakMap();
  const NAVIGATION_KEYS = new Set([
    "ArrowLeft",
    "ArrowRight",
    "ArrowUp",
    "ArrowDown",
    "Home",
    "End",
  ]);

  function readStored(storageKey) {
    if (!storageKey) return "";
    try {
      return global.sessionStorage?.getItem(storageKey) || "";
    } catch (_error) {
      return "";
    }
  }

  function storeActive(storageKey, value) {
    if (!storageKey) return;
    try {
      global.sessionStorage?.setItem(storageKey, value);
    } catch (_error) {
      // The tab remains functional when browser storage is unavailable.
    }
  }

  function create({
    root,
    tabSelector,
    panelSelector,
    tabDataKey,
    panelDataKey,
    defaultTab,
    storageKey = "",
  }) {
    if (!root) return null;
    if (controllers.has(root)) return controllers.get(root);

    const tabs = Array.from(root.querySelectorAll(tabSelector));
    const panels = Array.from(root.querySelectorAll(panelSelector));
    if (!tabs.length || !panels.length) return null;

    const tabValue = (tab) => tab.dataset[tabDataKey];
    const panelValue = (panel) => panel.dataset[panelDataKey];
    const isValid = (value) => tabs.some((tab) => tabValue(tab) === value);
    let activeValue = "";

    function activate(value, { focus = false } = {}) {
      const nextValue = isValid(value) ? value : defaultTab;
      if (!isValid(nextValue)) return;

      tabs.forEach((tab) => {
        const selected = tabValue(tab) === nextValue;
        tab.setAttribute("aria-selected", String(selected));
        tab.tabIndex = selected ? 0 : -1;
        if (selected && focus) tab.focus({ preventScroll: true });
      });
      panels.forEach((panel) => {
        panel.hidden = panelValue(panel) !== nextValue;
      });
      activeValue = nextValue;
      storeActive(storageKey, nextValue);
    }

    function handleKeydown(event) {
      if (!NAVIGATION_KEYS.has(event.key)) return;
      const currentIndex = tabs.indexOf(event.currentTarget);
      if (currentIndex < 0) return;

      let nextIndex = currentIndex;
      if (event.key === "Home") nextIndex = 0;
      if (event.key === "End") nextIndex = tabs.length - 1;
      if (event.key === "ArrowRight" || event.key === "ArrowDown") {
        nextIndex = (currentIndex + 1) % tabs.length;
      }
      if (event.key === "ArrowLeft" || event.key === "ArrowUp") {
        nextIndex = (currentIndex - 1 + tabs.length) % tabs.length;
      }

      event.preventDefault();
      activate(tabValue(tabs[nextIndex]), { focus: true });
    }

    tabs.forEach((tab) => {
      tab.addEventListener("click", (event) => {
        event.preventDefault();
        activate(tabValue(event.currentTarget));
      });
      tab.addEventListener("keydown", handleKeydown);
    });

    const controller = {
      activate,
      get active() {
        return activeValue;
      },
    };
    controllers.set(root, controller);
    activate(readStored(storageKey) || defaultTab);
    return controller;
  }

  app.tabs = { create };
})(globalThis);
