"use client";
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
import * as React from "react";
import { createContext, useContext } from "react";
import Link from "next/link";
import Image from "next/image";
import { ChevronUp, ChevronDown } from "lucide-react";
import { Button } from "../primitives/button.js";
import { IconButton } from "../primitives/icon-button.js";
import { FlashMessages } from "./FlashMessages.js";
import { QueryProvider } from "../theme/QueryProvider.js";
import { usePathname, useSearchParams } from "next/navigation";
import { apiCall } from "./utils/apiCall.js";
import { LastOperationBanner } from "./operations/LastOperationBanner.js";
import { ProgressTopBar } from "./progress/ProgressTopBar.js";
import { UpgradeActionBanner } from "./upgrades/UpgradeActionBanner.js";
import { PartialIndexBanner } from "./indexes/PartialIndexBanner.js";
import { useLocale, useT } from "@open-mercato/shared/lib/i18n/context";
import { slugifySidebarId } from "@open-mercato/shared/modules/navigation/sidebarPreferences";
import { InjectionSpot } from "./injection/InjectionSpot.js";
import { LEGACY_GLOBAL_MUTATION_INJECTION_SPOT_ID } from "./injection/mutationEvents.js";
import { mergeMenuItems } from "./injection/mergeMenuItems.js";
import { useInjectedMenuItems } from "./injection/useInjectedMenuItems.js";
import { resolveInjectedIcon } from "./injection/resolveInjectedIcon.js";
import { useEventBridge } from "./injection/eventBridge.js";
import { StatusBadgeInjectionSpot } from "./injection/StatusBadgeInjectionSpot.js";
import { UmesDevToolsPanel } from "./devtools/index.js";
import { BackendChromeProvider, useBackendChrome } from "./BackendChromeProvider.js";
import {
  BACKEND_LAYOUT_FOOTER_INJECTION_SPOT_ID,
  BACKEND_LAYOUT_TOP_INJECTION_SPOT_ID,
  BACKEND_RECORD_CURRENT_INJECTION_SPOT_ID,
  BACKEND_SIDEBAR_FOOTER_INJECTION_SPOT_ID,
  BACKEND_SIDEBAR_TOP_INJECTION_SPOT_ID,
  BACKEND_SIDEBAR_NAV_FOOTER_INJECTION_SPOT_ID,
  BACKEND_SIDEBAR_NAV_INJECTION_SPOT_ID,
  BACKEND_TOPBAR_ACTIONS_INJECTION_SPOT_ID,
  GLOBAL_HEADER_STATUS_INDICATORS_INJECTION_SPOT_ID,
  GLOBAL_SIDEBAR_STATUS_BADGES_INJECTION_SPOT_ID
} from "./injection/spotIds.js";
function convertInjectedMenuItemToSidebarItem(item, title) {
  if (!item.href) return null;
  return {
    id: item.id,
    href: item.href,
    title,
    defaultTitle: title,
    icon: resolveInjectedIcon(item.icon) ?? void 0,
    iconName: item.icon,
    enabled: true,
    hidden: false,
    pageContext: "main"
  };
}
function resolveInjectedMenuLabel(item, t) {
  if (item.labelKey && item.label) return t(item.labelKey, item.label);
  if (item.labelKey) return t(item.labelKey, item.id);
  if (item.label && item.label.includes(".")) return t(item.label, item.id);
  return item.label ?? item.id;
}
function mergeSidebarItemsWithInjected(items, injectedItems, t) {
  if (injectedItems.length === 0) return items;
  const builtInById = /* @__PURE__ */ new Map();
  for (const item of items) {
    builtInById.set(item.id ?? item.href, item);
  }
  const merged = mergeMenuItems(
    items.map((item) => ({
      id: item.id ?? item.href
    })),
    injectedItems
  );
  const result = [];
  for (const entry of merged) {
    if (entry.source === "built-in") {
      const original = builtInById.get(entry.id);
      if (original) result.push(original);
      continue;
    }
    const translatedLabel = resolveInjectedMenuLabel(
      { id: entry.id, label: entry.label, labelKey: entry.labelKey },
      t
    );
    const converted = convertInjectedMenuItemToSidebarItem(
      {
        id: entry.id,
        label: translatedLabel,
        icon: entry.icon,
        href: entry.href
      },
      translatedLabel
    );
    if (converted) result.push(converted);
  }
  return result;
}
function mergeSidebarGroupsWithInjected(groups, injectedItems, t) {
  if (injectedItems.length === 0) return groups;
  const injectedByGroup = /* @__PURE__ */ new Map();
  const ungrouped = [];
  for (const item of injectedItems) {
    if (item.groupId && item.groupId.trim().length > 0) {
      const groupItems = injectedByGroup.get(item.groupId) ?? [];
      groupItems.push(item);
      injectedByGroup.set(item.groupId, groupItems);
      continue;
    }
    ungrouped.push(item);
  }
  const nextGroups = groups.map((group, index) => {
    const groupId = group.id || resolveGroupKey(group);
    const groupInjected = [
      ...injectedByGroup.get(groupId) ?? [],
      ...index === 0 ? ungrouped : []
    ];
    return {
      ...group,
      items: mergeSidebarItemsWithInjected(group.items, groupInjected, t)
    };
  });
  const existingIds = new Set(nextGroups.map((group) => group.id || resolveGroupKey(group)));
  for (const [groupId, items] of injectedByGroup.entries()) {
    if (existingIds.has(groupId)) continue;
    const first = items[0];
    const label = first.groupLabelKey ? t(first.groupLabelKey, first.groupLabel ?? groupId) : first.groupLabel ?? groupId;
    const groupItems = mergeSidebarItemsWithInjected([], items, t);
    if (groupItems.length === 0) continue;
    nextGroups.push({
      id: groupId,
      name: label,
      defaultName: label,
      items: groupItems
    });
  }
  return nextGroups;
}
function mergeSectionGroupsWithInjected(sections, injectedItems, t) {
  if (injectedItems.length === 0) return sections;
  const byGroup = /* @__PURE__ */ new Map();
  for (const item of injectedItems) {
    const groupId = item.groupId && item.groupId.trim().length > 0 ? item.groupId : "injected";
    const bucket = byGroup.get(groupId) ?? [];
    bucket.push(item);
    byGroup.set(groupId, bucket);
  }
  const nextSections = sections.map((section) => {
    const sectionItems = byGroup.get(section.id) ?? [];
    if (sectionItems.length === 0) return section;
    const mergedItems = mergeMenuItems(
      section.items.map((item) => ({ id: item.id, item })),
      sectionItems
    ).flatMap((item) => {
      if (item.source === "built-in") {
        const original = section.items.find((entry) => entry.id === item.id);
        return original ? [original] : [];
      }
      if (!item.href) return [];
      const label = resolveInjectedMenuLabel(item, t);
      return [{
        id: item.id,
        label,
        href: item.href,
        icon: resolveInjectedIcon(item.icon) ?? void 0
      }];
    });
    return {
      ...section,
      items: mergedItems
    };
  });
  for (const [sectionId, sectionItems] of byGroup.entries()) {
    const exists = nextSections.some((section) => section.id === sectionId);
    if (exists) continue;
    const first = sectionItems[0];
    const label = first.groupLabelKey ? t(first.groupLabelKey, first.groupLabel ?? sectionId) : first.groupLabel ?? sectionId;
    const items = sectionItems.flatMap((item) => {
      if (!item.href) return [];
      const itemLabel = resolveInjectedMenuLabel(item, t);
      return [{
        id: item.id,
        label: itemLabel,
        href: item.href,
        icon: resolveInjectedIcon(item.icon) ?? void 0
      }];
    });
    if (items.length === 0) continue;
    nextSections.push({ id: sectionId, label, items });
  }
  return nextSections;
}
function resolveGroupKey(group) {
  if (group.id && group.id.length) return group.id;
  if (group.defaultName && group.defaultName.length) return slugifySidebarId(group.defaultName);
  return slugifySidebarId(group.name);
}
function resolveItemKey(item) {
  const candidate = item.id?.trim();
  if (candidate && candidate.length > 0) return candidate;
  return item.href;
}
function SerializedIcon({ markup }) {
  return /* @__PURE__ */ jsx("span", { "aria-hidden": "true", dangerouslySetInnerHTML: { __html: markup } });
}
function renderIcon(icon, iconName, iconMarkup, fallback) {
  if (icon) return icon;
  if (iconName) {
    const resolved = resolveInjectedIcon(iconName);
    if (resolved) return resolved;
  }
  if (iconMarkup) return /* @__PURE__ */ jsx(SerializedIcon, { markup: iconMarkup });
  return fallback;
}
const HeaderContext = createContext(null);
function ApplyBreadcrumb({ breadcrumb, title, titleKey }) {
  const ctx = useContext(HeaderContext);
  const t = useT();
  const resolvedBreadcrumb = React.useMemo(() => {
    if (!breadcrumb) return void 0;
    return breadcrumb.map(({ label, labelKey, href }) => {
      const translated = labelKey ? t(labelKey) : void 0;
      const finalLabel = translated && translated !== labelKey ? translated : label;
      return {
        href,
        label: finalLabel
      };
    });
  }, [breadcrumb, t]);
  const resolvedTitle = React.useMemo(() => {
    if (!titleKey) return title;
    const translated = t(titleKey);
    if (translated && translated !== titleKey) return translated;
    return title;
  }, [titleKey, title, t]);
  React.useEffect(() => {
    ctx?.setBreadcrumb(resolvedBreadcrumb);
    if (resolvedTitle !== void 0) ctx?.setTitle(resolvedTitle);
  }, [ctx, resolvedBreadcrumb, resolvedTitle]);
  return null;
}
const DefaultIcon = /* @__PURE__ */ jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
  /* @__PURE__ */ jsx("path", { d: "M8 6h13M8 12h13M8 18h13" }),
  /* @__PURE__ */ jsx("path", { d: "M3 6h.01M3 12h.01M3 18h.01" })
] });
const DataTableIcon = /* @__PURE__ */ jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
  /* @__PURE__ */ jsx("rect", { x: "3", y: "4", width: "18", height: "16", rx: "2", ry: "2" }),
  /* @__PURE__ */ jsx("line", { x1: "3", y1: "8", x2: "21", y2: "8" }),
  /* @__PURE__ */ jsx("line", { x1: "9", y1: "8", x2: "9", y2: "20" }),
  /* @__PURE__ */ jsx("line", { x1: "15", y1: "8", x2: "15", y2: "20" })
] });
const CustomizeIcon = /* @__PURE__ */ jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
  /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "3" }),
  /* @__PURE__ */ jsx("path", { d: "M19.4 15a1.65 1.65 0 0 0 .33 1.82l.05.05a2 2 0 1 1-2.83 2.83l-.05-.05A1.65 1.65 0 0 0 15 19.4a1.65 1.65 0 0 0-1 .6 1.65 1.65 0 0 0-.33 1.82l-.05.05a2 2 0 1 1-2.83-2.83l.05-.05A1.65 1.65 0 0 0 9 15a1.65 1.65 0 0 0-1-.6 1.65 1.65 0 0 0-1.82.33l-.05.05a2 2 0 1 1-2.83-2.83l.05-.05A1.65 1.65 0 0 0 4.6 9 1.65 1.65 0 0 0 4 8a1.65 1.65 0 0 0-.6-1.82l-.05-.05a2 2 0 1 1 2.83-2.83l.05.05A1.65 1.65 0 0 0 9 4.6a1.65 1.65 0 0 0 1-.6 1.65 1.65 0 0 0 .33-1.82l.05-.05a2 2 0 1 1 2.83 2.83l-.05.05A1.65 1.65 0 0 0 15 9a1.65 1.65 0 0 0 1 .6 1.65 1.65 0 0 0 1.82-.33l.05-.05a2 2 0 1 1 2.83 2.83l-.05.05A1.65 1.65 0 0 0 19.4 15z" })
] });
const BackArrowIcon = /* @__PURE__ */ jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M19 12H5M12 19l-7-7 7-7" }) });
function Chevron({ open }) {
  return /* @__PURE__ */ jsx("svg", { className: `transition-transform ${open ? "rotate-180" : ""}`, width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx("path", { d: "M6 9l6 6 6-6" }) });
}
function AppShell(props) {
  return /* @__PURE__ */ jsx(QueryProvider, { children: /* @__PURE__ */ jsx(BackendChromeProvider, { adminNavApi: props.adminNavApi, children: /* @__PURE__ */ jsx(AppShellBody, { ...props }) }) });
}
function AppShellBody({ productName, email, groups, rightHeaderSlot, children, sidebarCollapsedDefault = false, currentTitle, breadcrumb, version, settingsSectionTitle, settingsPathPrefixes = [], settingsSections, profileSections, profileSectionTitle, profilePathPrefixes = [], mobileSidebarSlot }) {
  const pathname = usePathname();
  const searchParams = useSearchParams();
  const t = useT();
  const locale = useLocale();
  const { payload: chromePayload, isReady: isChromeReady, isLoading: isChromeLoading } = useBackendChrome();
  const resolvedGroups = React.useMemo(
    () => AppShell.cloneGroups(chromePayload?.groups ?? groups),
    [chromePayload?.groups, groups]
  );
  const resolvedSettingsSections = chromePayload?.settingsSections ?? settingsSections;
  const resolvedSettingsPathPrefixes = chromePayload?.settingsPathPrefixes ?? settingsPathPrefixes;
  const resolvedProfileSections = chromePayload?.profileSections ?? profileSections;
  const resolvedProfilePathPrefixes = chromePayload?.profilePathPrefixes ?? profilePathPrefixes;
  const { items: mainSidebarInjectedMenuItems } = useInjectedMenuItems("menu:sidebar:main");
  const { items: settingsSidebarInjectedMenuItems } = useInjectedMenuItems("menu:sidebar:settings");
  const { items: profileSidebarInjectedMenuItems } = useInjectedMenuItems("menu:sidebar:profile");
  const { items: topbarInjectedMenuItems } = useInjectedMenuItems("menu:topbar:actions");
  useEventBridge();
  const resolvedProductName = productName ?? t("appShell.productName");
  const [mobileOpen, setMobileOpen] = React.useState(false);
  const [collapsed, setCollapsed] = React.useState(sidebarCollapsedDefault);
  const [navGroups, setNavGroups] = React.useState(resolvedGroups);
  const [openGroups, setOpenGroups] = React.useState(
    () => Object.fromEntries(resolvedGroups.map((g) => [resolveGroupKey(g), true]))
  );
  const [customizing, setCustomizing] = React.useState(false);
  const [customDraft, setCustomDraft] = React.useState(null);
  const [loadingPreferences, setLoadingPreferences] = React.useState(false);
  const [savingPreferences, setSavingPreferences] = React.useState(false);
  const [customizationError, setCustomizationError] = React.useState(null);
  const [availableRoleTargets, setAvailableRoleTargets] = React.useState([]);
  const [selectedRoleIds, setSelectedRoleIds] = React.useState([]);
  const [canApplyToRoles, setCanApplyToRoles] = React.useState(false);
  const originalNavRef = React.useRef(null);
  const [headerTitle, setHeaderTitle] = React.useState(currentTitle);
  const [headerBreadcrumb, setHeaderBreadcrumb] = React.useState(breadcrumb);
  const effectiveCollapsed = customizing ? false : collapsed;
  const expandedSidebarWidth = customizing ? "320px" : "240px";
  const injectionContext = React.useMemo(
    () => ({
      path: pathname ?? "",
      query: searchParams?.toString() ?? ""
    }),
    [pathname, searchParams]
  );
  const isOnSettingsPath = React.useMemo(() => {
    if (!pathname) return false;
    if (pathname === "/backend/settings") return true;
    return resolvedSettingsPathPrefixes.some((prefix) => pathname.startsWith(prefix));
  }, [pathname, resolvedSettingsPathPrefixes]);
  const isOnProfilePath = React.useMemo(() => {
    if (!pathname) return false;
    if (pathname === "/backend/profile") return true;
    return resolvedProfilePathPrefixes.some((prefix) => pathname.startsWith(prefix));
  }, [pathname, resolvedProfilePathPrefixes]);
  const sidebarMode = isOnSettingsPath ? "settings" : isOnProfilePath ? "profile" : "main";
  const mainNavGroupsWithInjected = React.useMemo(
    () => mergeSidebarGroupsWithInjected(navGroups, mainSidebarInjectedMenuItems, t),
    [mainSidebarInjectedMenuItems, navGroups, t]
  );
  React.useEffect(() => {
    if (!mobileOpen || typeof document === "undefined") return;
    const prev = document.body.style.overflow;
    document.body.style.overflow = "hidden";
    return () => {
      document.body.style.overflow = prev;
    };
  }, [mobileOpen]);
  React.useEffect(() => {
    try {
      const savedOpen = typeof window !== "undefined" ? localStorage.getItem("om:sidebarOpenGroups") : null;
      if (!savedOpen) return;
      const parsed = JSON.parse(savedOpen);
      setOpenGroups((prev) => {
        const next = { ...prev };
        for (const group of resolvedGroups) {
          const key = resolveGroupKey(group);
          if (key in parsed) next[key] = !!parsed[key];
          else if (group.name in parsed) next[key] = !!parsed[group.name];
        }
        return next;
      });
    } catch {
    }
  }, [resolvedGroups]);
  const toggleGroup = (groupId) => setOpenGroups((prev) => ({ ...prev, [groupId]: prev[groupId] === false }));
  const updateDraft = React.useCallback((updater) => {
    setCustomDraft((prev) => {
      if (!prev) return prev;
      const next = updater(prev);
      if (originalNavRef.current) {
        setNavGroups(applyCustomizationDraft(originalNavRef.current, next));
      }
      return next;
    });
  }, []);
  const startCustomization = React.useCallback(async () => {
    if (customizing || loadingPreferences) return;
    setCustomizationError(null);
    setLoadingPreferences(true);
    try {
      const baseSnapshot = filterMainSidebarGroups(AppShell.cloneGroups(navGroups));
      const call = await apiCall("/api/auth/sidebar/preferences");
      const data = call.ok ? call.result ?? null : null;
      const rawSettings = data?.settings;
      const responseOrder = Array.isArray(rawSettings?.groupOrder) ? rawSettings.groupOrder.map((id) => typeof id === "string" ? id.trim() : "").filter((id) => id.length > 0) : [];
      const responseGroupLabels = {};
      if (rawSettings?.groupLabels && typeof rawSettings.groupLabels === "object") {
        for (const [key, value] of Object.entries(rawSettings.groupLabels)) {
          if (typeof value !== "string") continue;
          const trimmedKey = key.trim();
          if (!trimmedKey) continue;
          responseGroupLabels[trimmedKey] = value;
        }
      }
      const responseItemLabels = {};
      if (rawSettings?.itemLabels && typeof rawSettings.itemLabels === "object") {
        for (const [key, value] of Object.entries(rawSettings.itemLabels)) {
          if (typeof value !== "string") continue;
          const trimmedKey = key.trim();
          if (!trimmedKey) continue;
          responseItemLabels[trimmedKey] = value;
        }
      }
      const responseHiddenItems = Array.isArray(rawSettings?.hiddenItems) ? rawSettings.hiddenItems.map((itemId) => typeof itemId === "string" ? itemId.trim() : "").filter((itemId) => itemId.length > 0) : [];
      const canManageRoles = data?.canApplyToRoles === true;
      setCanApplyToRoles(canManageRoles);
      if (canManageRoles) {
        const roles = Array.isArray(data?.roles) ? data.roles.filter((role) => typeof role?.id === "string" && typeof role?.name === "string") : [];
        const mappedRoles = roles.map((role) => ({
          id: role.id,
          name: role.name,
          hasPreference: role.hasPreference === true
        }));
        setAvailableRoleTargets(mappedRoles);
        setSelectedRoleIds(mappedRoles.filter((role) => role.hasPreference).map((role) => role.id));
      } else {
        setAvailableRoleTargets([]);
        setSelectedRoleIds([]);
      }
      const currentIds = baseSnapshot.map((group) => resolveGroupKey(group));
      const order = mergeGroupOrder(responseOrder, currentIds);
      const { itemDefaults } = collectSidebarDefaults(baseSnapshot);
      const hiddenItemIds = {};
      for (const itemId of responseHiddenItems) {
        if (!itemDefaults.has(itemId)) continue;
        hiddenItemIds[itemId] = true;
      }
      const draft = {
        order,
        groupLabels: { ...responseGroupLabels },
        itemLabels: { ...responseItemLabels },
        hiddenItemIds
      };
      originalNavRef.current = baseSnapshot;
      setCustomDraft(draft);
      setNavGroups(applyCustomizationDraft(baseSnapshot, draft));
      setCustomizing(true);
    } catch (error) {
      console.error("Failed to load sidebar preferences", error);
      setCustomizationError(t("appShell.sidebarCustomizationLoadError"));
    } finally {
      setLoadingPreferences(false);
    }
  }, [customizing, loadingPreferences, navGroups, t]);
  const cancelCustomization = React.useCallback(() => {
    setCustomizing(false);
    setCustomDraft(null);
    setCustomizationError(null);
    setAvailableRoleTargets([]);
    setSelectedRoleIds([]);
    setCanApplyToRoles(false);
    if (originalNavRef.current) {
      setNavGroups(AppShell.cloneGroups(originalNavRef.current));
    }
    originalNavRef.current = null;
  }, []);
  const resetCustomization = React.useCallback(() => {
    if (!originalNavRef.current) return;
    const base = AppShell.cloneGroups(originalNavRef.current);
    const order = base.map((group) => resolveGroupKey(group));
    const draft = { order, groupLabels: {}, itemLabels: {}, hiddenItemIds: {} };
    originalNavRef.current = base;
    setCustomDraft(draft);
    setNavGroups(applyCustomizationDraft(base, draft));
    if (canApplyToRoles) {
      setSelectedRoleIds(availableRoleTargets.filter((role) => role.hasPreference).map((role) => role.id));
    }
  }, [availableRoleTargets, canApplyToRoles]);
  const saveCustomization = React.useCallback(async () => {
    if (!customDraft) return;
    setSavingPreferences(true);
    setCustomizationError(null);
    try {
      const baseGroups = originalNavRef.current ?? filterMainSidebarGroups(AppShell.cloneGroups(navGroups));
      const { groupDefaults, itemDefaults } = collectSidebarDefaults(baseGroups);
      const sanitizedGroupLabels = {};
      for (const [key, value] of Object.entries(customDraft.groupLabels)) {
        const trimmed = value.trim();
        const base = groupDefaults.get(key);
        if (!trimmed || !base) continue;
        if (trimmed !== base) sanitizedGroupLabels[key] = trimmed;
      }
      const sanitizedItemLabels = {};
      for (const [itemId, value] of Object.entries(customDraft.itemLabels)) {
        const trimmed = value.trim();
        const base = itemDefaults.get(itemId);
        if (!trimmed || !base) continue;
        if (trimmed !== base) sanitizedItemLabels[itemId] = trimmed;
      }
      const sanitizedHiddenItems = [];
      for (const [itemId, hidden] of Object.entries(customDraft.hiddenItemIds)) {
        if (!hidden) continue;
        if (!itemDefaults.has(itemId)) continue;
        sanitizedHiddenItems.push(itemId);
      }
      const applyToRolesPayload = canApplyToRoles ? [...selectedRoleIds] : [];
      const clearRoleIdsPayload = canApplyToRoles ? availableRoleTargets.filter((role) => role.hasPreference && !selectedRoleIds.includes(role.id)).map((role) => role.id) : [];
      const payload = {
        groupOrder: customDraft.order,
        groupLabels: sanitizedGroupLabels,
        itemLabels: sanitizedItemLabels,
        hiddenItems: sanitizedHiddenItems
      };
      if (canApplyToRoles) {
        payload.applyToRoles = applyToRolesPayload;
        payload.clearRoleIds = clearRoleIdsPayload;
      }
      const call = await apiCall("/api/auth/sidebar/preferences", {
        method: "PUT",
        headers: { "content-type": "application/json" },
        body: JSON.stringify(payload)
      });
      if (!call.ok) {
        setCustomizationError(t("appShell.sidebarCustomizationSaveError"));
        return;
      }
      const data = call.result ?? null;
      if (data?.canApplyToRoles !== void 0) {
        setCanApplyToRoles(data.canApplyToRoles === true);
      }
      if (Array.isArray(data?.roles)) {
        const mappedRoles = data.roles.filter((role) => typeof role?.id === "string" && typeof role?.name === "string").map((role) => ({
          id: role.id,
          name: role.name,
          hasPreference: role.hasPreference === true
        }));
        setAvailableRoleTargets(mappedRoles);
        setSelectedRoleIds(mappedRoles.filter((role) => role.hasPreference).map((role) => role.id));
      }
      originalNavRef.current = applyCustomizationDraft(baseGroups, customDraft);
      setNavGroups(AppShell.cloneGroups(originalNavRef.current));
      setCustomizing(false);
      setCustomDraft(null);
      try {
        window.dispatchEvent(new Event("om:refresh-sidebar"));
      } catch {
      }
    } catch (error) {
      console.error("Failed to save sidebar preferences", error);
      setCustomizationError(t("appShell.sidebarCustomizationSaveError"));
    } finally {
      setSavingPreferences(false);
    }
  }, [customDraft, navGroups, t]);
  const moveGroup = React.useCallback((groupId, offset) => {
    updateDraft((draft) => {
      const order = [...draft.order];
      const index = order.indexOf(groupId);
      if (index === -1) return draft;
      const nextIndex = Math.max(0, Math.min(order.length - 1, index + offset));
      if (nextIndex === index) return draft;
      order.splice(index, 1);
      order.splice(nextIndex, 0, groupId);
      return { ...draft, order };
    });
  }, [updateDraft]);
  const setGroupLabel = React.useCallback((groupId, value) => {
    updateDraft((draft) => {
      const next = { ...draft.groupLabels };
      if (value.trim().length === 0) delete next[groupId];
      else next[groupId] = value;
      return { ...draft, groupLabels: next };
    });
  }, [updateDraft]);
  const setItemLabel = React.useCallback((itemId, value) => {
    updateDraft((draft) => {
      const next = { ...draft.itemLabels };
      if (value.trim().length === 0) delete next[itemId];
      else next[itemId] = value;
      return { ...draft, itemLabels: next };
    });
  }, [updateDraft]);
  const setItemHidden = React.useCallback((itemId, hidden) => {
    updateDraft((draft) => {
      const next = { ...draft.hiddenItemIds };
      if (hidden) next[itemId] = true;
      else delete next[itemId];
      return { ...draft, hiddenItemIds: next };
    });
  }, [updateDraft]);
  const toggleRoleSelection = React.useCallback((roleId) => {
    setSelectedRoleIds((prev) => prev.includes(roleId) ? prev.filter((id) => id !== roleId) : [...prev, roleId]);
  }, []);
  const asideWidth = effectiveCollapsed ? "72px" : expandedSidebarWidth;
  const asideClassesBase = `border-r bg-background/60 py-4 min-h-svh`;
  React.useEffect(() => {
    try {
      localStorage.setItem("om:sidebarCollapsed", collapsed ? "1" : "0");
    } catch {
    }
    try {
      document.cookie = `om_sidebar_collapsed=${collapsed ? "1" : "0"}; path=/; max-age=31536000; samesite=lax`;
    } catch {
    }
  }, [collapsed]);
  React.useEffect(() => {
    try {
      localStorage.setItem("om:sidebarOpenGroups", JSON.stringify(openGroups));
    } catch {
    }
  }, [openGroups]);
  React.useEffect(() => {
    const activeGroup = navGroups.find((g) => g.items.some((i) => pathname?.startsWith(i.href)));
    if (!activeGroup) return;
    const key = resolveGroupKey(activeGroup);
    setOpenGroups((prev) => prev[key] === false ? { ...prev, [key]: true } : prev);
  }, [pathname, navGroups]);
  React.useEffect(() => {
    setHeaderTitle(currentTitle);
    setHeaderBreadcrumb(breadcrumb);
  }, [currentTitle, breadcrumb]);
  const prevPathname = React.useRef(pathname);
  React.useEffect(() => {
    if (pathname !== prevPathname.current) {
      prevPathname.current = pathname;
      setHeaderTitle(void 0);
      setHeaderBreadcrumb(void 0);
    }
  }, [pathname]);
  React.useEffect(() => {
    if (customizing && customDraft && originalNavRef.current) {
      originalNavRef.current = filterMainSidebarGroups(AppShell.cloneGroups(resolvedGroups));
      setNavGroups(applyCustomizationDraft(originalNavRef.current, customDraft));
      return;
    }
    setNavGroups(AppShell.cloneGroups(resolvedGroups));
  }, [resolvedGroups, customizing, customDraft]);
  function renderSectionSidebar(sections, title, compact, hideHeader) {
    const sortedSections = [...sections].sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
    const lastVisibleIndex = sortedSections.length - 1;
    return /* @__PURE__ */ jsxs("div", { className: "flex flex-col min-h-full gap-3", children: [
      !hideHeader && /* @__PURE__ */ jsx("div", { className: `flex items-center ${compact ? "justify-center" : "justify-between"} mb-2`, children: /* @__PURE__ */ jsxs(Link, { href: "/backend", className: "flex items-center gap-2", "aria-label": t("appShell.goToDashboard"), children: [
        /* @__PURE__ */ jsx(Image, { src: "/open-mercato.svg", alt: resolvedProductName, width: 32, height: 32, className: "rounded m-4" }),
        !compact && /* @__PURE__ */ jsx("div", { className: "text-m font-semibold", children: resolvedProductName })
      ] }) }),
      /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col gap-3 overflow-y-auto pr-1", children: [
        /* @__PURE__ */ jsxs(
          Link,
          {
            href: "/backend",
            className: `flex items-center gap-2 ${compact ? "justify-center px-2" : "px-2"} py-1 text-sm text-muted-foreground hover:text-foreground transition-colors`,
            "aria-label": t("backend.nav.backToMain", "Back"),
            children: [
              /* @__PURE__ */ jsx("span", { className: "flex items-center justify-center shrink-0", children: BackArrowIcon }),
              !compact && /* @__PURE__ */ jsx("span", { children: title })
            ]
          }
        ),
        /* @__PURE__ */ jsx("nav", { className: "flex flex-col gap-2", children: sortedSections.map((section, sectionIndex) => {
          const visibleItems = section.items;
          if (visibleItems.length === 0) return null;
          const sortedItems = [...visibleItems].sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
          const sectionLabel = section.labelKey ? t(section.labelKey, section.label) : section.label;
          const sectionKey = `settings:${section.id}`;
          const open = openGroups[sectionKey] !== false;
          const sortSectionItems = (items = []) => [...items].sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
          const renderSectionItem = (item, depth = 0) => {
            const label = item.labelKey ? t(item.labelKey, item.label) : item.label;
            const childItems = sortSectionItems(item.children);
            const isOnItemBranch = !!pathname && (pathname === item.href || pathname.startsWith(`${item.href}/`));
            const hasActiveChild = !!(pathname && childItems.some((child) => pathname === child.href || pathname.startsWith(`${child.href}/`)));
            const showChildren = childItems.length > 0 && isOnItemBranch;
            const isActive = isOnItemBranch || hasActiveChild;
            const base = compact ? "w-10 h-10 justify-center" : "py-1 gap-2";
            const spacingStyle = !compact ? {
              paddingLeft: `${8 + depth * 16}px`,
              paddingRight: "8px"
            } : void 0;
            return /* @__PURE__ */ jsxs(React.Fragment, { children: [
              /* @__PURE__ */ jsxs(
                Link,
                {
                  href: item.href,
                  className: `relative text-sm rounded inline-flex items-center ${base} ${isActive ? "bg-background border shadow-sm" : "hover:bg-accent hover:text-accent-foreground"}`,
                  style: spacingStyle,
                  title: compact ? label : void 0,
                  "data-menu-item-id": item.id,
                  onClick: () => setMobileOpen(false),
                  children: [
                    isActive && /* @__PURE__ */ jsx("span", { className: "absolute left-0 top-1 bottom-1 w-0.5 rounded bg-foreground" }),
                    /* @__PURE__ */ jsx("span", { className: `flex items-center justify-center shrink-0 ${compact ? "" : "text-muted-foreground"}`, children: renderIcon(
                      item.icon,
                      item.iconName,
                      item.iconMarkup,
                      item.href.includes("/backend/entities/user/") && item.href.endsWith("/records") ? DataTableIcon : DefaultIcon
                    ) }),
                    !compact && /* @__PURE__ */ jsx("span", { className: "truncate", children: label })
                  ]
                }
              ),
              showChildren ? childItems.map((child) => renderSectionItem(child, depth + 1)) : null
            ] }, item.id);
          };
          return /* @__PURE__ */ jsxs("div", { children: [
            /* @__PURE__ */ jsxs(
              Button,
              {
                variant: "muted",
                onClick: () => toggleGroup(sectionKey),
                className: `w-full ${compact ? "px-0 justify-center" : "px-2 justify-between"} flex text-xs uppercase text-muted-foreground/90 py-2`,
                "aria-expanded": open,
                children: [
                  !compact && /* @__PURE__ */ jsx("span", { children: sectionLabel }),
                  !compact && /* @__PURE__ */ jsx(Chevron, { open })
                ]
              }
            ),
            open && /* @__PURE__ */ jsx("div", { className: `flex flex-col ${compact ? "items-center" : ""} gap-1 ${!compact ? "pl-1" : ""}`, children: sortedItems.map((item) => renderSectionItem(item)) }),
            sectionIndex !== lastVisibleIndex && /* @__PURE__ */ jsx("div", { className: "my-2 border-t border-dotted" })
          ] }, section.id);
        }) })
      ] })
    ] });
  }
  function renderSidebar(compact, hideHeader) {
    if (!isChromeReady && isChromeLoading && resolvedGroups.length === 0) {
      return /* @__PURE__ */ jsxs("div", { className: "flex flex-col min-h-full gap-3", "data-testid": "backend-chrome-loading", children: [
        !hideHeader ? /* @__PURE__ */ jsx("div", { className: `flex items-center ${compact ? "justify-center" : "justify-between"} mb-2`, children: /* @__PURE__ */ jsxs(Link, { href: "/backend", className: "flex items-center gap-2", "aria-label": t("appShell.goToDashboard"), children: [
          /* @__PURE__ */ jsx(Image, { src: "/open-mercato.svg", alt: resolvedProductName, width: 32, height: 32, className: "rounded m-4" }),
          !compact && /* @__PURE__ */ jsx("div", { className: "text-m font-semibold", children: resolvedProductName })
        ] }) }) : null,
        /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col gap-3 pr-1", children: [
          /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
            /* @__PURE__ */ jsx("div", { className: "h-8 rounded bg-muted/60" }),
            /* @__PURE__ */ jsxs("div", { className: "space-y-2 pl-1", children: [
              /* @__PURE__ */ jsx("div", { className: "h-8 rounded bg-muted/50" }),
              /* @__PURE__ */ jsx("div", { className: "h-8 rounded bg-muted/40" }),
              /* @__PURE__ */ jsx("div", { className: "h-8 rounded bg-muted/40" })
            ] })
          ] }),
          /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
            /* @__PURE__ */ jsx("div", { className: "h-8 rounded bg-muted/60" }),
            /* @__PURE__ */ jsxs("div", { className: "space-y-2 pl-1", children: [
              /* @__PURE__ */ jsx("div", { className: "h-8 rounded bg-muted/40" }),
              /* @__PURE__ */ jsx("div", { className: "h-8 rounded bg-muted/40" })
            ] })
          ] })
        ] })
      ] });
    }
    if (sidebarMode === "settings" && resolvedSettingsSections && resolvedSettingsSections.length > 0) {
      const mergedSettingsSections = mergeSectionGroupsWithInjected(
        resolvedSettingsSections,
        settingsSidebarInjectedMenuItems,
        t
      );
      return renderSectionSidebar(
        mergedSettingsSections,
        settingsSectionTitle ?? t("backend.nav.settings", "Settings"),
        compact,
        hideHeader
      );
    }
    if (sidebarMode === "profile" && resolvedProfileSections && resolvedProfileSections.length > 0) {
      const mergedProfileSections = mergeSectionGroupsWithInjected(
        resolvedProfileSections,
        profileSidebarInjectedMenuItems,
        t
      );
      return renderSectionSidebar(
        mergedProfileSections,
        profileSectionTitle ?? t("backend.nav.profile", "Profile"),
        compact,
        hideHeader
      );
    }
    const isMobileVariant = !!hideHeader;
    const shouldRenderSidebarInjectionSpots = !isMobileVariant;
    const baseGroupsForDefaults = originalNavRef.current ?? mainNavGroupsWithInjected;
    const baseGroupMap = /* @__PURE__ */ new Map();
    for (const group of baseGroupsForDefaults) {
      baseGroupMap.set(resolveGroupKey(group), group);
    }
    const localeLabel = (locale || "").toUpperCase();
    const orderedGroupIds = customDraft ? mergeGroupOrder(customDraft.order, Array.from(baseGroupMap.keys())) : mainNavGroupsWithInjected.map((group) => resolveGroupKey(group));
    const lastVisibleGroupIndex = (() => {
      for (let idx = navGroups.length - 1; idx >= 0; idx -= 1) {
        if (navGroups[idx].items.some((item) => item.hidden !== true)) return idx;
      }
      return -1;
    })();
    const renderEditableItems = (baseItems, currentItems, depth = 0) => {
      if (!customDraft) return null;
      return baseItems.map((baseItem) => {
        const itemKey = resolveItemKey(baseItem);
        const current = currentItems.find((item) => item.href === baseItem.href) ?? baseItem;
        const placeholder = baseItem.defaultTitle ?? baseItem.title;
        const value = customDraft.itemLabels[itemKey] ?? "";
        const hidden = customDraft.hiddenItemIds[itemKey] === true;
        return /* @__PURE__ */ jsxs(
          "div",
          {
            className: `flex flex-col gap-1 ${hidden ? "opacity-60" : ""}`,
            style: depth ? { marginLeft: depth * 16 } : void 0,
            children: [
              /* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-muted-foreground", children: placeholder }),
              /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
                /* @__PURE__ */ jsx(
                  "input",
                  {
                    type: "checkbox",
                    className: "h-4 w-4 accent-foreground",
                    checked: !hidden,
                    onChange: (event) => setItemHidden(itemKey, !event.target.checked),
                    disabled: savingPreferences,
                    "aria-label": t("appShell.sidebarCustomizationShowItem"),
                    title: t("appShell.sidebarCustomizationShowItem")
                  }
                ),
                /* @__PURE__ */ jsx(
                  "input",
                  {
                    value,
                    onChange: (event) => setItemLabel(itemKey, event.target.value),
                    placeholder,
                    disabled: savingPreferences,
                    className: "h-8 flex-1 rounded border bg-background px-2 text-sm shadow-sm focus:outline-none focus:ring-2 focus:ring-ring disabled:opacity-60"
                  }
                )
              ] }),
              baseItem.children && baseItem.children.length > 0 ? /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-1", children: renderEditableItems(baseItem.children, current.children ?? [], depth + 1) }) : null
            ]
          },
          itemKey
        );
      });
    };
    const customizationEditor = customizing ? customDraft ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 rounded border border-dashed bg-muted/20 p-3", children: [
      /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-between gap-2", children: [
        /* @__PURE__ */ jsx("div", { className: "text-sm font-semibold", children: t("appShell.sidebarCustomizationHeading") }),
        /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
          /* @__PURE__ */ jsx(
            Button,
            {
              variant: "outline",
              size: "sm",
              onClick: resetCustomization,
              disabled: savingPreferences,
              children: t("appShell.sidebarCustomizationReset")
            }
          ),
          /* @__PURE__ */ jsx(
            Button,
            {
              variant: "outline",
              size: "sm",
              onClick: cancelCustomization,
              disabled: savingPreferences,
              children: t("appShell.sidebarCustomizationCancel")
            }
          ),
          /* @__PURE__ */ jsx(
            Button,
            {
              size: "sm",
              className: "bg-foreground text-background hover:bg-foreground/90",
              onClick: saveCustomization,
              disabled: savingPreferences,
              children: savingPreferences ? t("appShell.sidebarCustomizationSaving") : t("appShell.sidebarCustomizationSave")
            }
          )
        ] })
      ] }),
      /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: t("appShell.sidebarCustomizationHint", { locale: localeLabel }) }),
      canApplyToRoles ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2 rounded border bg-background/70 p-3 shadow-sm", children: [
        /* @__PURE__ */ jsxs("div", { children: [
          /* @__PURE__ */ jsx("div", { className: "text-sm font-semibold", children: t("appShell.sidebarApplyToRolesTitle") }),
          /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: t("appShell.sidebarApplyToRolesDescription") })
        ] }),
        availableRoleTargets.length > 0 ? /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-2", children: availableRoleTargets.map((role) => {
          const checked = selectedRoleIds.includes(role.id);
          const willClear = role.hasPreference && !checked;
          return /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 rounded border bg-background px-2 py-1 text-sm shadow-sm", children: [
            /* @__PURE__ */ jsx(
              "input",
              {
                type: "checkbox",
                className: "h-4 w-4 accent-foreground",
                checked,
                onChange: () => toggleRoleSelection(role.id),
                disabled: savingPreferences
              }
            ),
            /* @__PURE__ */ jsx("span", { className: "flex-1 truncate", children: role.name }),
            role.hasPreference ? /* @__PURE__ */ jsx("span", { className: `text-xs ${willClear ? "text-destructive" : "text-muted-foreground"}`, children: willClear ? t("appShell.sidebarRoleWillClear") : t("appShell.sidebarRoleHasPreset") }) : null
          ] }, role.id);
        }) }) : /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: t("appShell.sidebarApplyToRolesEmpty") })
      ] }) : null,
      customizationError ? /* @__PURE__ */ jsx("p", { className: "text-xs text-destructive", children: customizationError }) : null,
      /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-3", children: orderedGroupIds.map((groupId, index) => {
        const baseGroup = baseGroupMap.get(groupId);
        if (!baseGroup) return null;
        const currentGroup = navGroups.find((group) => resolveGroupKey(group) === groupId) ?? baseGroup;
        const placeholder = baseGroup.defaultName ?? baseGroup.name;
        const value = customDraft.groupLabels[groupId] ?? "";
        return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 rounded border bg-background p-3 shadow-sm", children: [
          /* @__PURE__ */ jsxs("div", { className: `flex ${compact ? "flex-col gap-2" : "items-center gap-2"}`, children: [
            /* @__PURE__ */ jsxs("div", { className: "flex-1", children: [
              /* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-muted-foreground", children: t("appShell.sidebarCustomizationGroupLabel") }),
              /* @__PURE__ */ jsx(
                "input",
                {
                  value,
                  onChange: (event) => setGroupLabel(groupId, event.target.value),
                  placeholder,
                  disabled: savingPreferences,
                  className: "mt-1 h-8 w-full rounded border bg-background px-2 text-sm shadow-sm focus:outline-none focus:ring-2 focus:ring-ring disabled:opacity-60"
                }
              )
            ] }),
            /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 self-start", children: [
              /* @__PURE__ */ jsx(
                IconButton,
                {
                  variant: "outline",
                  size: "sm",
                  className: "text-muted-foreground hover:text-foreground",
                  onClick: () => moveGroup(groupId, -1),
                  disabled: index === 0 || savingPreferences,
                  "aria-label": t("appShell.sidebarCustomizationMoveUp"),
                  children: /* @__PURE__ */ jsx(ChevronUp, { className: "size-4" })
                }
              ),
              /* @__PURE__ */ jsx(
                IconButton,
                {
                  variant: "outline",
                  size: "sm",
                  className: "text-muted-foreground hover:text-foreground",
                  onClick: () => moveGroup(groupId, 1),
                  disabled: index === orderedGroupIds.length - 1 || savingPreferences,
                  "aria-label": t("appShell.sidebarCustomizationMoveDown"),
                  children: /* @__PURE__ */ jsx(ChevronDown, { className: "size-4" })
                }
              )
            ] })
          ] }),
          /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-2", children: renderEditableItems(baseGroup.items, currentGroup.items) })
        ] }, groupId);
      }) })
    ] }) : /* @__PURE__ */ jsx("div", { className: "rounded border border-dashed bg-muted/20 p-3 text-sm text-muted-foreground", children: t("appShell.sidebarCustomizationLoading") }) : null;
    return /* @__PURE__ */ jsxs("div", { className: "flex flex-col min-h-full gap-3", children: [
      !hideHeader && /* @__PURE__ */ jsx("div", { className: `flex items-center ${compact ? "justify-center" : "justify-between"} mb-2`, children: /* @__PURE__ */ jsxs(Link, { href: "/backend", className: "flex items-center gap-2", "aria-label": t("appShell.goToDashboard"), children: [
        /* @__PURE__ */ jsx(Image, { src: "/open-mercato.svg", alt: resolvedProductName, width: 32, height: 32, className: "rounded m-4" }),
        !compact && /* @__PURE__ */ jsx("div", { className: "text-m font-semibold", children: resolvedProductName })
      ] }) }),
      shouldRenderSidebarInjectionSpots ? /* @__PURE__ */ jsx(
        InjectionSpot,
        {
          spotId: BACKEND_SIDEBAR_TOP_INJECTION_SPOT_ID,
          context: injectionContext
        }
      ) : null,
      /* @__PURE__ */ jsx("div", { className: "flex flex-1 flex-col gap-3 pr-1", children: customizing ? customizationEditor : (() => {
        const isSettingsPath = (href) => {
          if (href === "/backend/settings") return true;
          return resolvedSettingsPathPrefixes.some((prefix) => href.startsWith(prefix));
        };
        const isMainItem = (item) => {
          if (item.pageContext && item.pageContext !== "main") return false;
          if (isSettingsPath(item.href)) return false;
          return true;
        };
        const mainGroups = mainNavGroupsWithInjected.map((g) => ({
          ...g,
          items: g.items.filter((item) => isMainItem(item) && item.hidden !== true)
        })).filter((g) => g.items.length > 0);
        const mainLastVisibleGroupIndex = (() => {
          for (let idx = mainGroups.length - 1; idx >= 0; idx -= 1) {
            if (mainGroups[idx].items.some((item) => item.hidden !== true)) return idx;
          }
          return -1;
        })();
        return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs("nav", { className: "flex flex-col gap-2", "data-testid": "sidebar", children: [
          shouldRenderSidebarInjectionSpots ? /* @__PURE__ */ jsx(
            InjectionSpot,
            {
              spotId: BACKEND_SIDEBAR_NAV_INJECTION_SPOT_ID,
              context: injectionContext
            }
          ) : null,
          mainGroups.map((g, gi) => {
            const groupId = resolveGroupKey(g);
            const open = openGroups[groupId] !== false;
            const visibleItems = g.items.filter((item) => item.hidden !== true);
            if (visibleItems.length === 0) return null;
            return /* @__PURE__ */ jsxs("div", { children: [
              /* @__PURE__ */ jsxs(
                Button,
                {
                  variant: "muted",
                  onClick: () => toggleGroup(groupId),
                  className: `w-full ${compact ? "px-0 justify-center" : "px-2 justify-between"} flex text-xs uppercase text-muted-foreground/90 py-2`,
                  "aria-expanded": open,
                  children: [
                    !compact && /* @__PURE__ */ jsx("span", { children: g.name }),
                    !compact && /* @__PURE__ */ jsx(Chevron, { open })
                  ]
                }
              ),
              open && /* @__PURE__ */ jsx("div", { className: `flex flex-col ${compact ? "items-center" : ""} gap-1 ${!compact ? "pl-1" : ""}`, children: visibleItems.map((i) => {
                const childItems = (i.children ?? []).filter((child) => child.hidden !== true);
                const showChildren = !!pathname && childItems.length > 0 && pathname.startsWith(i.href);
                const hasActiveChild = !!(pathname && childItems.some((c) => pathname.startsWith(c.href)));
                const isParentActive = pathname === i.href || showChildren && !hasActiveChild;
                const base = compact ? "w-10 h-10 justify-center" : "px-2 py-1 gap-2";
                return /* @__PURE__ */ jsxs(React.Fragment, { children: [
                  /* @__PURE__ */ jsxs(
                    Link,
                    {
                      href: i.href,
                      className: `relative text-sm rounded inline-flex items-center ${base} ${isParentActive ? "bg-background border shadow-sm" : "hover:bg-accent hover:text-accent-foreground"} ${i.enabled === false ? "pointer-events-none opacity-50" : ""}`,
                      "aria-disabled": i.enabled === false,
                      title: compact ? i.title : void 0,
                      "data-menu-item-id": i.id ?? i.href,
                      onClick: () => setMobileOpen(false),
                      children: [
                        isParentActive ? /* @__PURE__ */ jsx("span", { className: "absolute left-0 top-1 bottom-1 w-0.5 rounded bg-foreground" }) : null,
                        /* @__PURE__ */ jsx("span", { className: `flex items-center justify-center shrink-0 ${compact ? "" : "text-muted-foreground"}`, children: renderIcon(
                          i.icon,
                          i.iconName,
                          i.iconMarkup,
                          DefaultIcon
                        ) }),
                        !compact && /* @__PURE__ */ jsx("span", { children: i.title })
                      ]
                    }
                  ),
                  showChildren ? /* @__PURE__ */ jsx("div", { className: `flex flex-col ${compact ? "items-center" : ""} gap-1 ${!compact ? "pl-4" : ""}`, children: childItems.map((c) => {
                    const childActive = pathname?.startsWith(c.href);
                    const childBase = compact ? "w-10 h-8 justify-center" : "px-2 py-1 gap-2";
                    return /* @__PURE__ */ jsxs(
                      Link,
                      {
                        href: c.href,
                        className: `relative text-sm rounded inline-flex items-center ${childBase} ${childActive ? "bg-background border shadow-sm" : "hover:bg-accent hover:text-accent-foreground"} ${c.enabled === false ? "pointer-events-none opacity-50" : ""}`,
                        "aria-disabled": c.enabled === false,
                        title: compact ? c.title : void 0,
                        "data-menu-item-id": c.id ?? c.href,
                        onClick: () => setMobileOpen(false),
                        children: [
                          childActive ? /* @__PURE__ */ jsx("span", { className: "absolute left-0 top-1 bottom-1 w-0.5 rounded bg-foreground" }) : null,
                          /* @__PURE__ */ jsx("span", { className: `flex items-center justify-center shrink-0 ${compact ? "" : "text-muted-foreground"}`, children: renderIcon(
                            c.icon,
                            c.iconName,
                            c.iconMarkup,
                            c.href.includes("/backend/entities/user/") && c.href.endsWith("/records") ? DataTableIcon : DefaultIcon
                          ) }),
                          !compact && /* @__PURE__ */ jsx("span", { children: c.title })
                        ]
                      },
                      c.href
                    );
                  }) }) : null
                ] }, i.href);
              }) }),
              gi !== mainLastVisibleGroupIndex && /* @__PURE__ */ jsx("div", { className: "my-2 border-t border-dotted" })
            ] }, groupId);
          })
        ] }) });
      })() }),
      /* @__PURE__ */ jsxs("div", { className: "sticky bottom-0 pt-4 border-t bg-background/60 backdrop-blur-sm pb-1", children: [
        shouldRenderSidebarInjectionSpots ? /* @__PURE__ */ jsx(
          InjectionSpot,
          {
            spotId: BACKEND_SIDEBAR_NAV_FOOTER_INJECTION_SPOT_ID,
            context: injectionContext
          }
        ) : null,
        /* @__PURE__ */ jsxs(
          Link,
          {
            href: "/backend/settings",
            className: `relative text-sm rounded inline-flex items-center w-full ${compact ? "w-10 h-10 justify-center" : "px-2 py-1 gap-2"} ${pathname?.startsWith("/backend/settings") || pathname?.startsWith("/backend/config") || pathname?.startsWith("/backend/users") || pathname?.startsWith("/backend/roles") || pathname?.startsWith("/backend/api-keys") || pathname?.startsWith("/backend/entities") || pathname?.startsWith("/backend/query-indexes") || pathname?.startsWith("/backend/definitions") || pathname?.startsWith("/backend/instances") || pathname?.startsWith("/backend/tasks") || pathname?.startsWith("/backend/events") || pathname?.startsWith("/backend/rules") || pathname?.startsWith("/backend/sets") || pathname?.startsWith("/backend/logs") || pathname?.startsWith("/backend/directory") || pathname?.startsWith("/backend/feature-toggles") ? "bg-background border shadow-sm font-medium" : "hover:bg-accent hover:text-accent-foreground"}`,
            title: compact ? t("backend.nav.settings", "Settings") : void 0,
            onClick: () => setMobileOpen(false),
            children: [
              (pathname?.startsWith("/backend/settings") || pathname?.startsWith("/backend/config") || pathname?.startsWith("/backend/users") || pathname?.startsWith("/backend/roles") || pathname?.startsWith("/backend/api-keys") || pathname?.startsWith("/backend/entities") || pathname?.startsWith("/backend/query-indexes") || pathname?.startsWith("/backend/definitions") || pathname?.startsWith("/backend/instances") || pathname?.startsWith("/backend/tasks") || pathname?.startsWith("/backend/events") || pathname?.startsWith("/backend/rules") || pathname?.startsWith("/backend/sets") || pathname?.startsWith("/backend/logs") || pathname?.startsWith("/backend/directory") || pathname?.startsWith("/backend/feature-toggles")) && /* @__PURE__ */ jsx("span", { className: "absolute left-0 top-1 bottom-1 w-0.5 rounded bg-foreground" }),
              /* @__PURE__ */ jsx("span", { className: `flex items-center justify-center shrink-0 ${compact ? "" : "text-muted-foreground"}`, children: /* @__PURE__ */ jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
                /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "3" }),
                /* @__PURE__ */ jsx("path", { d: "M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z" })
              ] }) }),
              !compact && /* @__PURE__ */ jsx("span", { children: t("backend.nav.settings", "Settings") })
            ]
          }
        ),
        !customizing && /* @__PURE__ */ jsxs("div", { className: "mt-2", children: [
          shouldRenderSidebarInjectionSpots ? /* @__PURE__ */ jsx(
            StatusBadgeInjectionSpot,
            {
              spotId: GLOBAL_SIDEBAR_STATUS_BADGES_INJECTION_SPOT_ID,
              context: injectionContext
            }
          ) : null,
          compact || isMobileVariant ? /* @__PURE__ */ jsx(
            IconButton,
            {
              variant: "outline",
              size: "lg",
              onClick: startCustomization,
              disabled: loadingPreferences,
              "aria-label": t("appShell.customizeSidebar"),
              children: CustomizeIcon
            }
          ) : /* @__PURE__ */ jsxs(
            Button,
            {
              variant: "outline",
              size: "default",
              onClick: startCustomization,
              disabled: loadingPreferences,
              "aria-label": t("appShell.customizeSidebar"),
              children: [
                CustomizeIcon,
                loadingPreferences ? t("appShell.sidebarCustomizationLoading") : t("appShell.customizeSidebar")
              ]
            }
          )
        ] }),
        shouldRenderSidebarInjectionSpots ? /* @__PURE__ */ jsx(
          InjectionSpot,
          {
            spotId: BACKEND_SIDEBAR_FOOTER_INJECTION_SPOT_ID,
            context: injectionContext
          }
        ) : null
      ] })
    ] });
  }
  const gridColsClass = customizing ? "lg:grid-cols-[320px_1fr]" : effectiveCollapsed ? "lg:grid-cols-[72px_1fr]" : "lg:grid-cols-[240px_1fr]";
  const headerCtxValue = React.useMemo(() => ({
    setBreadcrumb: setHeaderBreadcrumb,
    setTitle: setHeaderTitle
  }), []);
  const renderedTopbarInjectedActions = React.useMemo(
    () => topbarInjectedMenuItems.map((item) => {
      const label = resolveInjectedMenuLabel(item, t);
      if (item.href) {
        return /* @__PURE__ */ jsx(
          Link,
          {
            href: item.href,
            className: "inline-flex items-center rounded border px-2 py-1 text-xs hover:bg-accent hover:text-accent-foreground",
            "data-menu-item-id": item.id,
            children: label
          },
          item.id
        );
      }
      return /* @__PURE__ */ jsx(
        Button,
        {
          type: "button",
          variant: "outline",
          size: "sm",
          className: "h-7 text-xs",
          "data-menu-item-id": item.id,
          onClick: () => item.onClick?.(),
          children: label
        },
        item.id
      );
    }),
    [t, topbarInjectedMenuItems]
  );
  return /* @__PURE__ */ jsxs(HeaderContext.Provider, { value: headerCtxValue, children: [
    /* @__PURE__ */ jsxs("div", { className: `min-h-svh lg:grid ${gridColsClass}`, children: [
      /* @__PURE__ */ jsx("aside", { className: `${asideClassesBase} ${effectiveCollapsed ? "px-2" : "px-3"} hidden lg:block`, style: { width: asideWidth }, children: renderSidebar(effectiveCollapsed) }),
      /* @__PURE__ */ jsxs("div", { className: "flex min-h-svh flex-col min-w-0", children: [
        /* @__PURE__ */ jsxs("header", { className: "border-b bg-background/60 px-3 lg:px-4 py-2 lg:py-3 flex items-center justify-between gap-2", children: [
          /* @__PURE__ */ jsx(
            "div",
            {
              "data-testid": "backend-chrome-ready",
              "data-ready": isChromeReady ? "true" : "false",
              className: "hidden"
            }
          ),
          /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 min-w-0", children: [
            /* @__PURE__ */ jsx(IconButton, { variant: "outline", size: "sm", className: "lg:hidden", "aria-label": t("appShell.openMenu"), onClick: () => setMobileOpen(true), children: /* @__PURE__ */ jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx("path", { d: "M3 6h18M3 12h18M3 18h18" }) }) }),
            /* @__PURE__ */ jsx(
              IconButton,
              {
                variant: "outline",
                size: "sm",
                className: "hidden lg:inline-flex",
                "aria-label": t("appShell.toggleSidebar"),
                onClick: () => setCollapsed((c) => !c),
                disabled: customizing,
                children: /* @__PURE__ */ jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
                  /* @__PURE__ */ jsx("rect", { x: "3", y: "4", width: "18", height: "16", rx: "2" }),
                  /* @__PURE__ */ jsx("path", { d: "M9 4v16" })
                ] })
              }
            ),
            (() => {
              const dashboardLabel = t("dashboard.title");
              const root = [{ label: dashboardLabel, href: "/backend" }];
              let rest = [];
              if (headerBreadcrumb && headerBreadcrumb.length) {
                const first = headerBreadcrumb[0];
                const dup = first && (first.href === "/backend" || first.label === dashboardLabel || first.label?.toLowerCase() === "dashboard");
                rest = dup ? headerBreadcrumb.slice(1) : headerBreadcrumb;
              } else if (headerTitle) {
                rest = [{ label: headerTitle }];
              }
              const items = [...root, ...rest];
              const lastIndex = items.length - 1;
              return /* @__PURE__ */ jsx("nav", { className: "flex items-center gap-2 text-sm min-w-0", children: items.map((b, i) => {
                const isLast = i === lastIndex;
                const hiddenOnMobile = !isLast ? "hidden md:inline" : "";
                return /* @__PURE__ */ jsxs(React.Fragment, { children: [
                  i > 0 && /* @__PURE__ */ jsx("span", { className: `text-muted-foreground hidden md:inline`, children: "/" }),
                  b.href ? /* @__PURE__ */ jsx(Link, { href: b.href, className: `text-muted-foreground hover:text-foreground ${hiddenOnMobile}`, children: b.label }) : /* @__PURE__ */ jsx("span", { className: `font-medium truncate max-w-[45vw] md:max-w-[60vw]`, children: b.label })
                ] }, i);
              }) });
            })()
          ] }),
          /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 md:gap-2 text-sm shrink-0", children: [
            /* @__PURE__ */ jsx(
              StatusBadgeInjectionSpot,
              {
                spotId: GLOBAL_HEADER_STATUS_INDICATORS_INJECTION_SPOT_ID,
                context: injectionContext
              }
            ),
            /* @__PURE__ */ jsx(
              InjectionSpot,
              {
                spotId: BACKEND_TOPBAR_ACTIONS_INJECTION_SPOT_ID,
                context: injectionContext
              }
            ),
            renderedTopbarInjectedActions,
            rightHeaderSlot ? rightHeaderSlot : /* @__PURE__ */ jsx("span", { className: "opacity-80", children: email || t("appShell.userFallback") })
          ] })
        ] }),
        /* @__PURE__ */ jsx(ProgressTopBar, { t, className: "sticky top-0 z-10" }),
        /* @__PURE__ */ jsxs("main", { className: "flex-1 p-4 lg:p-6", children: [
          /* @__PURE__ */ jsx(InjectionSpot, { spotId: BACKEND_LAYOUT_TOP_INJECTION_SPOT_ID, context: injectionContext }),
          /* @__PURE__ */ jsx(FlashMessages, {}),
          /* @__PURE__ */ jsx(PartialIndexBanner, {}),
          /* @__PURE__ */ jsx(UpgradeActionBanner, {}),
          /* @__PURE__ */ jsx(LastOperationBanner, {}),
          /* @__PURE__ */ jsx(InjectionSpot, { spotId: BACKEND_RECORD_CURRENT_INJECTION_SPOT_ID, context: injectionContext }),
          /* @__PURE__ */ jsx(
            InjectionSpot,
            {
              spotId: LEGACY_GLOBAL_MUTATION_INJECTION_SPOT_ID,
              context: injectionContext
            }
          ),
          /* @__PURE__ */ jsx("div", { id: "om-top-banners", className: "mb-3 space-y-2" }),
          children,
          /* @__PURE__ */ jsx(InjectionSpot, { spotId: BACKEND_LAYOUT_FOOTER_INJECTION_SPOT_ID, context: injectionContext })
        ] }),
        /* @__PURE__ */ jsxs("footer", { className: "border-t bg-background/80 backdrop-blur supports-[backdrop-filter]:bg-background/50 px-4 py-3 flex flex-wrap items-center justify-end gap-4", children: [
          version ? /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: t("appShell.version", { version }) }) : null,
          /* @__PURE__ */ jsxs("nav", { className: "flex items-center gap-3 text-xs text-muted-foreground", children: [
            /* @__PURE__ */ jsx(Link, { href: "/terms", className: "transition hover:text-foreground", children: t("common.terms") }),
            /* @__PURE__ */ jsx(Link, { href: "/privacy", className: "transition hover:text-foreground", children: t("common.privacy") })
          ] })
        ] })
      ] }),
      mobileOpen && /* @__PURE__ */ jsxs("div", { className: "lg:hidden fixed inset-0 z-50", children: [
        /* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-black/40", onClick: () => setMobileOpen(false), "aria-hidden": "true" }),
        /* @__PURE__ */ jsxs("aside", { className: "absolute left-0 top-0 flex h-full w-[260px] flex-col bg-background border-r overflow-hidden", children: [
          /* @__PURE__ */ jsxs("div", { className: "shrink-0 p-3 pb-2 flex items-center justify-between border-b", children: [
            /* @__PURE__ */ jsxs(Link, { href: "/backend", className: "flex items-center gap-2 text-sm font-semibold", onClick: () => setMobileOpen(false), "aria-label": t("appShell.goToDashboard"), children: [
              /* @__PURE__ */ jsx(Image, { src: "/open-mercato.svg", alt: resolvedProductName, width: 28, height: 28, className: "rounded" }),
              resolvedProductName
            ] }),
            /* @__PURE__ */ jsx(IconButton, { variant: "outline", size: "sm", onClick: () => setMobileOpen(false), "aria-label": t("appShell.closeMenu"), children: "\u2715" })
          ] }),
          mobileSidebarSlot && /* @__PURE__ */ jsx("div", { className: "shrink-0 border-b px-3 py-2", children: mobileSidebarSlot }),
          /* @__PURE__ */ jsx("div", { className: "min-h-0 flex-1 overflow-y-auto overflow-x-hidden p-3", children: renderSidebar(false, true) })
        ] })
      ] })
    ] }),
    /* @__PURE__ */ jsx(UmesDevToolsPanel, {})
  ] });
}
AppShell.cloneGroups = function cloneGroups(groups) {
  const cloneItem = (item) => ({
    id: item.id,
    href: item.href,
    title: item.title,
    defaultTitle: item.defaultTitle,
    icon: item.icon,
    iconName: item.iconName,
    iconMarkup: item.iconMarkup,
    enabled: item.enabled,
    hidden: item.hidden,
    pageContext: item.pageContext,
    children: item.children ? item.children.map((child) => cloneItem(child)) : void 0
  });
  return groups.map((group) => ({
    id: group.id,
    name: group.name,
    defaultName: group.defaultName,
    items: group.items.map((item) => cloneItem(item))
  }));
};
function applyCustomizationDraft(baseGroups, draft) {
  const clones = AppShell.cloneGroups(baseGroups);
  const byId = /* @__PURE__ */ new Map();
  for (const group of clones) {
    byId.set(resolveGroupKey(group), group);
  }
  const orderedIds = mergeGroupOrder(draft.order, Array.from(byId.keys()));
  const seen = /* @__PURE__ */ new Set();
  const result = [];
  for (const id of orderedIds) {
    if (seen.has(id)) continue;
    const group = byId.get(id);
    if (!group) continue;
    seen.add(id);
    const baseName = group.defaultName ?? group.name;
    const override = draft.groupLabels[id]?.trim();
    result.push({
      ...group,
      name: override && override.length > 0 ? override : baseName,
      items: group.items.map((item) => applyItemDraft(item, draft))
    });
  }
  return result;
}
function applyItemDraft(item, draft) {
  const itemKey = resolveItemKey(item);
  const baseTitle = item.defaultTitle ?? item.title;
  const override = draft.itemLabels[itemKey]?.trim();
  const children = item.children ? item.children.map((child) => applyItemDraft(child, draft)) : void 0;
  const hidden = draft.hiddenItemIds[itemKey] === true;
  return {
    ...item,
    title: override && override.length > 0 ? override : baseTitle,
    hidden,
    children
  };
}
function mergeGroupOrder(preferred, current) {
  const seen = /* @__PURE__ */ new Set();
  const merged = [];
  for (const id of preferred) {
    const trimmed = id.trim();
    if (!trimmed || seen.has(trimmed) || !current.includes(trimmed)) continue;
    seen.add(trimmed);
    merged.push(trimmed);
  }
  for (const id of current) {
    if (seen.has(id)) continue;
    seen.add(id);
    merged.push(id);
  }
  return merged;
}
function collectSidebarDefaults(groups) {
  const groupDefaults = /* @__PURE__ */ new Map();
  const itemDefaults = /* @__PURE__ */ new Map();
  const visitItems = (items) => {
    for (const item of items) {
      const key = resolveItemKey(item);
      const baseTitle = item.defaultTitle ?? item.title;
      itemDefaults.set(key, baseTitle);
      itemDefaults.set(item.href, baseTitle);
      if (item.children && item.children.length > 0) visitItems(item.children);
    }
  };
  for (const group of groups) {
    const key = resolveGroupKey(group);
    groupDefaults.set(key, group.defaultName ?? group.name);
    visitItems(group.items);
  }
  return { groupDefaults, itemDefaults };
}
function filterMainSidebarGroups(groups) {
  const isMainItem = (item) => {
    if (item.pageContext && item.pageContext !== "main") return false;
    return true;
  };
  return groups.map((group) => ({
    ...group,
    items: group.items.filter(isMainItem).map((item) => ({
      ...item,
      children: item.children?.filter(isMainItem)
    }))
  })).filter((group) => group.items.length > 0);
}
export {
  AppShell,
  ApplyBreadcrumb
};
//# sourceMappingURL=AppShell.js.map
