(function () {
  "use strict";

  const region = document.getElementById("workspace-region");
  const navigation = document.getElementById("workspace-navigation");
  const navigationItems = document.getElementById("workspace-nav-items");
  const toggle = document.getElementById("workspace-nav-toggle");
  const toggleLabel = toggle && toggle.querySelector(".workspace-nav-toggle-label");
  const stockTab = document.getElementById("workspace-stock-tab");
  const settingsTab = document.getElementById("workspace-settings-tab");
  const stockWorkspace = document.getElementById("stock-workspace");
  const catalogWorkspace = document.getElementById("catalog-workspace");
  const settingsWorkspace = document.getElementById("settings-workspace");
  const marketTabs = document.getElementById("market-tabs");
  const title = document.getElementById("workspace-title");
  const titleIcon = document.querySelector(".workspace-heading-icon");
  const shell = document.querySelector(".operator-shell");
  const splitter = document.getElementById("workspace-splitter");
  const playlistPanel = document.querySelector(".playlist-panel");
  const brandWordmark = document.querySelector("img.brand-wordmark");
  const brandWordmarkPlate = brandWordmark?.closest(".brand-wordmark-plate");

  function showBrandWordmarkFallback() {
    brandWordmarkPlate?.classList.add("wordmark-fallback-active");
  }

  if (brandWordmark) {
    brandWordmark.addEventListener("error", showBrandWordmarkFallback, { once: true });
    if (brandWordmark.complete && brandWordmark.naturalWidth === 0) {
      showBrandWordmarkFallback();
    }
  }

  if (!region || !navigation || !navigationItems || !toggle || !toggleLabel ||
      !stockTab || !settingsTab || !stockWorkspace || !catalogWorkspace ||
      !settingsWorkspace || !marketTabs || !title) {
    return;
  }

  const views = Object.freeze({
    stock: Object.freeze({ view: stockWorkspace, title: "종목·컷" }),
    catalog: Object.freeze({ view: catalogWorkspace, title: "기타 그래픽" }),
    settings: Object.freeze({ view: settingsWorkspace, title: "설정" })
  });
  let activeWorkspace = "stock";
  let activeMarketTabId = marketTabs.querySelector("button.active[data-tab-id]")
    ?.dataset.tabId || marketTabs.querySelector("button[data-tab-id]")?.dataset.tabId || null;
  let pendingKeyboardMarketTabId = null;
  let rememberWorkspaceChanges = false;
  let startPreferenceApplied = false;
  let splitterGesture = null;
  let scheduleWidthPercent = null;
  const lastWorkspaceStorageKey = "mbn-stock-webview.last-workspace.v1";
  const scheduleWidthStorageKey = "mbn-stock-webview.schedule-width.v1";
  const scheduleMinimumPercent = 34;
  const scheduleMaximumPercent = 48;
  const workspaceMinimumPixels = 780;
  const scheduleMinimumPixels = 600;
  const splitterPixels = 8;

  function readStoredValue(key) {
    try {
      return window.localStorage && window.localStorage.getItem(key);
    } catch (_) {
      return null;
    }
  }

  function writeStoredValue(key, value) {
    try {
      if (window.localStorage) window.localStorage.setItem(key, value);
    } catch (_) {
      // Presentation preferences must never interrupt operator input.
    }
  }

  function currentWorkspaceToken() {
    if (activeWorkspace !== "catalog") return activeWorkspace;
    return activeMarketTabId ? "catalog:" + activeMarketTabId : "stock";
  }

  function rememberActiveWorkspace() {
    if (!rememberWorkspaceChanges) return;
    writeStoredValue(lastWorkspaceStorageKey, currentWorkspaceToken());
  }

  function storedWorkspaceToken() {
    const token = readStoredValue(lastWorkspaceStorageKey);
    if (token === "stock" || token === "settings") return token;
    if (typeof token !== "string" || !token.startsWith("catalog:")) return null;
    const tabId = token.slice("catalog:".length);
    return marketButton(tabId) ? token : null;
  }

  function marketButtons() {
    return Array.from(marketTabs.querySelectorAll("button[data-tab-id]"));
  }

  function marketButton(tabId) {
    return marketButtons().find(function (button) {
      return button.dataset.tabId === tabId;
    }) || null;
  }

  function marketLabel(button) {
    const label = button && button.querySelector(".workspace-nav-label");
    return (label && label.textContent.trim()) || button?.textContent.trim() || views.catalog.title;
  }

  function selectedMenuButton(name) {
    if (name === "stock") return stockTab;
    if (name === "settings") return settingsTab;
    if (name === "catalog") {
      return marketButton(activeMarketTabId) || marketButtons()[0] || null;
    }
    return null;
  }

  function syncHeadingIcon(button) {
    const source = button && button.querySelector("svg.workspace-nav-icon[data-icon]");
    if (!titleIcon || !source) return;
    const next = source.cloneNode(true);
    next.removeAttribute("aria-hidden");
    titleIcon.dataset.icon = source.dataset.icon || "";
    titleIcon.replaceChildren(next);
  }

  function refreshCurrentMenu() {
    const selected = selectedMenuButton(activeWorkspace);
    Array.from(navigation.querySelectorAll(".workspace-nav-item")).forEach(function (button) {
      const isCurrent = button === selected;
      button.classList.toggle("workspace-current", isCurrent);
      button.setAttribute("aria-current", isCurrent ? "page" : "false");
    });
    region.dataset.activeWorkspace = activeWorkspace;
    if (activeMarketTabId) region.dataset.activeMarketTab = activeMarketTabId;
  }

  function setNavigationExpanded(expanded) {
    const isExpanded = expanded === true;
    region.classList.toggle("nav-collapsed", !isExpanded);
    toggle.setAttribute("aria-expanded", isExpanded ? "true" : "false");
    toggle.setAttribute("aria-label", isExpanded ? "작업 메뉴 접기" : "작업 메뉴 펼치기");
    toggle.title = isExpanded ? "메뉴 접기" : "메뉴 펼치기";
    toggleLabel.textContent = isExpanded ? "메뉴 접기" : "메뉴 펼치기";
  }

  function setWorkspace(name) {
    const selected = views[name];
    if (!selected) return false;

    const selectedButton = selectedMenuButton(name);
    const currentFocus = document.activeElement;
    const focusWillBeHidden = Object.keys(views).some(function (key) {
      return key !== name && views[key].view.contains(currentFocus);
    });
    if (focusWillBeHidden && selectedButton) selectedButton.focus();

    Object.keys(views).forEach(function (key) {
      const entry = views[key];
      const isCurrent = key === name;
      entry.view.hidden = !isCurrent;
      entry.view.toggleAttribute("inert", !isCurrent);
      entry.view.setAttribute("aria-hidden", isCurrent ? "false" : "true");
    });

    activeWorkspace = name;
    refreshCurrentMenu();
    syncHeadingIcon(selectedButton);
    title.textContent = name === "catalog"
      ? marketLabel(selectedMenuButton(name))
      : selected.title;
    rememberActiveWorkspace();
    return true;
  }

  function applyStartPreference(mode) {
    if (startPreferenceApplied) return true;
    const token = mode === "lastWorkspace" ? storedWorkspaceToken() : "stock";
    if (!token || token === "stock" || token === "settings") {
      startPreferenceApplied = true;
      return setWorkspace(token === "settings" ? "settings" : "stock");
    }

    const tabId = token.slice("catalog:".length);
    const button = marketButton(tabId);
    if (!button || button.disabled) return false;
    startPreferenceApplied = true;
    if (activeMarketTabId === tabId) {
      syncMarket(tabId);
      return setWorkspace("catalog");
    }
    button.click();
    return true;
  }

  function numericScheduleBounds() {
    if (!shell) {
      return { minimum: scheduleMinimumPercent, maximum: scheduleMaximumPercent };
    }
    const width = shell.getBoundingClientRect().width;
    if (!Number.isFinite(width) || width <= 0) {
      return { minimum: scheduleMinimumPercent, maximum: scheduleMaximumPercent };
    }
    const minimum = Math.max(
      scheduleMinimumPercent,
      scheduleMinimumPixels / width * 100);
    const maximum = Math.min(
      scheduleMaximumPercent,
      (width - workspaceMinimumPixels - splitterPixels) / width * 100);
    return {
      minimum: Math.min(minimum, maximum),
      maximum: Math.max(minimum, maximum)
    };
  }

  function clampScheduleWidth(value) {
    const bounds = numericScheduleBounds();
    return Math.min(bounds.maximum, Math.max(bounds.minimum, value));
  }

  function applyScheduleWidth(value, persist) {
    if (!shell || !splitter || !Number.isFinite(value)) return false;
    scheduleWidthPercent = clampScheduleWidth(value);
    const serialized = scheduleWidthPercent.toFixed(3) + "%";
    shell.style.setProperty("--schedule-pane-width", serialized);
    const bounds = numericScheduleBounds();
    const rounded = Math.round(scheduleWidthPercent);
    splitter.setAttribute("aria-valuemin", bounds.minimum.toFixed(1));
    splitter.setAttribute("aria-valuemax", bounds.maximum.toFixed(1));
    splitter.setAttribute("aria-valuenow", scheduleWidthPercent.toFixed(1));
    splitter.setAttribute("aria-valuetext", "송출 스케줄 " + rounded + "%");
    if (persist === true) {
      writeStoredValue(scheduleWidthStorageKey, scheduleWidthPercent.toFixed(3));
    }
    return true;
  }

  function schedulePercentFromPointer(clientX) {
    const bounds = shell.getBoundingClientRect();
    return (bounds.right - clientX) / bounds.width * 100;
  }

  function finishSplitterGesture(restore) {
    if (!splitterGesture || !splitter) return;
    const gesture = splitterGesture;
    splitterGesture = null;
    if (splitter.hasPointerCapture?.(gesture.pointerId)) {
      splitter.releasePointerCapture(gesture.pointerId);
    }
    document.body.classList.remove("resizing-workspace");
    splitter.classList.remove("dragging");
    applyScheduleWidth(
      restore === true ? gesture.startPercent : scheduleWidthPercent,
      restore !== true);
  }

  function initializeSplitter() {
    if (!shell || !splitter || !playlistPanel) return;
    const stored = Number.parseFloat(readStoredValue(scheduleWidthStorageKey));
    let initial = Number.isFinite(stored) ? stored : null;
    if (initial === null) {
      const shellBounds = shell.getBoundingClientRect();
      const scheduleBounds = playlistPanel.getBoundingClientRect();
      initial = shellBounds.width > 0
        ? scheduleBounds.width / shellBounds.width * 100
        : 40;
    }
    applyScheduleWidth(initial, false);

    splitter.addEventListener("pointerdown", function (event) {
      if (event.button !== 0 || event.isPrimary === false || splitterGesture) return;
      splitterGesture = {
        pointerId: event.pointerId,
        startPercent: scheduleWidthPercent
      };
      splitter.setPointerCapture?.(event.pointerId);
      splitter.classList.add("dragging");
      document.body.classList.add("resizing-workspace");
      splitter.focus({ preventScroll: true });
      event.preventDefault();
    });
    splitter.addEventListener("pointermove", function (event) {
      if (!splitterGesture || splitterGesture.pointerId !== event.pointerId ||
          (event.buttons & 1) === 0) return;
      applyScheduleWidth(schedulePercentFromPointer(event.clientX), false);
      event.preventDefault();
    });
    splitter.addEventListener("pointerup", function (event) {
      if (!splitterGesture || splitterGesture.pointerId !== event.pointerId) return;
      finishSplitterGesture(false);
      event.preventDefault();
    });
    splitter.addEventListener("pointercancel", function (event) {
      if (!splitterGesture || splitterGesture.pointerId !== event.pointerId) return;
      finishSplitterGesture(true);
    });
    splitter.addEventListener("lostpointercapture", function (event) {
      if (!splitterGesture || splitterGesture.pointerId !== event.pointerId) return;
      finishSplitterGesture(false);
    });
    splitter.addEventListener("keydown", function (event) {
      if (event.key === "Escape" && splitterGesture) {
        event.preventDefault();
        event.stopImmediatePropagation();
        finishSplitterGesture(true);
        return;
      }
      let next = scheduleWidthPercent;
      if (event.key === "ArrowLeft") next += 2;
      else if (event.key === "ArrowRight") next -= 2;
      else if (event.key === "Home") next = numericScheduleBounds().minimum;
      else if (event.key === "End") next = numericScheduleBounds().maximum;
      else return;
      event.preventDefault();
      event.stopPropagation();
      applyScheduleWidth(next, true);
    });
    window.addEventListener("resize", function () {
      window.requestAnimationFrame(function () {
        applyScheduleWidth(scheduleWidthPercent, false);
      });
    });
  }

  function syncMarket(tabId, options) {
    const button = marketButton(tabId);
    if (!button) return false;
    activeMarketTabId = tabId;
    region.dataset.activeMarketTab = tabId;
    if (activeWorkspace === "catalog") {
      refreshCurrentMenu();
      syncHeadingIcon(button);
      title.textContent = marketLabel(button);
    }
    const authoritativeNativeRender = options &&
      options.authoritativeNativeRender === true;
    if (authoritativeNativeRender && pendingKeyboardMarketTabId &&
        pendingKeyboardMarketTabId !== tabId) {
      // The native operation completed on a different tab. Do not carry a
      // failed or superseded keyboard request into a later render.
      pendingKeyboardMarketTabId = null;
    }
    if (authoritativeNativeRender && pendingKeyboardMarketTabId === tabId &&
        !button.disabled) {
      const pendingTabId = pendingKeyboardMarketTabId;
      // Native loading temporarily disables the selected menu button, which
      // can move focus to <body>. Only the final, non-busy native render may
      // consume this request; the optimistic capture-phase click must not.
      window.requestAnimationFrame(function () {
        if (pendingKeyboardMarketTabId !== pendingTabId) return;
        pendingKeyboardMarketTabId = null;
        const pendingButton = marketButton(pendingTabId);
        const active = document.activeElement;
        const focusWasLost = !active ||
          active === document.body ||
          active === document.documentElement;
        if (activeWorkspace === "catalog" && pendingButton &&
            !pendingButton.disabled && focusWasLost) {
          pendingButton.focus();
        }
      });
    }
    return true;
  }

  function hasPendingKeyboardMarketFocus(tabId) {
    return pendingKeyboardMarketTabId !== null &&
      (tabId === undefined || tabId === pendingKeyboardMarketTabId);
  }

  function select(name) {
    if (views[name]) return setWorkspace(name);
    if (!syncMarket(name)) return false;
    return setWorkspace("catalog");
  }

  function focusAdjacentItem(direction) {
    const items = Array.from(navigation.querySelectorAll(".workspace-nav-item"))
      .filter(function (button) { return button.disabled !== true; });
    if (items.length === 0) return;
    const currentIndex = items.indexOf(document.activeElement);
    const nextIndex = currentIndex < 0
      ? 0
      : (currentIndex + direction + items.length) % items.length;
    items[nextIndex].focus();
  }

  toggle.addEventListener("click", function () {
    setNavigationExpanded(toggle.getAttribute("aria-expanded") !== "true");
  });
  stockTab.addEventListener("click", function () {
    startPreferenceApplied = true;
    setWorkspace("stock");
  });
  settingsTab.addEventListener("click", function () {
    startPreferenceApplied = true;
    setWorkspace("settings");
  });

  navigation.addEventListener("keydown", function (event) {
    const menuButton = event.target.closest && event.target.closest(".workspace-nav-item");
    if (!menuButton) return;
    if (event.key === "Enter" || event.key === " ") {
      event.preventDefault();
      event.stopPropagation();
      const keyboardMarketTabId = menuButton.dataset.tabId || null;
      pendingKeyboardMarketTabId = keyboardMarketTabId;
      menuButton.click();
      return;
    }
    if (event.key === "Tab") {
      pendingKeyboardMarketTabId = null;
      return;
    }
    if (event.key !== "ArrowUp" && event.key !== "ArrowDown") return;
    event.preventDefault();
    event.stopPropagation();
    focusAdjacentItem(event.key === "ArrowUp" ? -1 : 1);
  });

  document.addEventListener("pointerdown", function () {
    // A real pointer action transfers focus ownership to the user. A delayed
    // native response must never pull it back to the keyboard-selected menu.
    pendingKeyboardMarketTabId = null;
  }, true);

  // Reveal the selected catalog screen before app.js dispatches its native
  // select-tab intent. The native state response remains authoritative and
  // is reconciled through syncMarket after every render.
  marketTabs.addEventListener("click", function (event) {
    const button = event.target.closest("button[data-tab-id]");
    if (!button || !marketTabs.contains(button)) return;
    startPreferenceApplied = true;
    syncMarket(button.dataset.tabId);
    setWorkspace("catalog");
  }, true);

  setNavigationExpanded(true);
  setWorkspace("stock");
  rememberWorkspaceChanges = true;
  initializeSplitter();

  window.LegacyWorkspaceNavigation = Object.freeze({
    select: select,
    syncMarket: syncMarket,
    hasPendingKeyboardMarketFocus: hasPendingKeyboardMarketFocus,
    setExpanded: setNavigationExpanded,
    applyStartPreference: applyStartPreference,
    active: function () { return activeWorkspace; },
    activeMarket: function () { return activeMarketTabId; },
    expanded: function () { return toggle.getAttribute("aria-expanded") === "true"; },
    scheduleWidth: function () { return scheduleWidthPercent; }
  });
}());
