"use client";
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
import * as React from "react";
import { ChevronUp, ChevronDown, GripVertical, RotateCcw, Trash2, Plus, Search, AlertTriangle } from "lucide-react";
import { DndContext, closestCenter, PointerSensor, KeyboardSensor, useSensor, useSensors } from "@dnd-kit/core";
import { SortableContext, verticalListSortingStrategy, useSortable, arrayMove } from "@dnd-kit/sortable";
import { CSS } from "@dnd-kit/utilities";
import Image from "next/image";
import { resolveInjectedIcon } from "../injection/resolveInjectedIcon.js";
import { useT, useLocale } from "@open-mercato/shared/lib/i18n/context";
import { Button } from "../../primitives/button.js";
import { IconButton } from "../../primitives/icon-button.js";
import { Input } from "../../primitives/input.js";
import { Switch } from "../../primitives/switch.js";
import { Card, CardContent, CardHeader, CardTitle } from "../../primitives/card.js";
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "../../primitives/dialog.js";
import { Tag } from "../../primitives/tag.js";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue
} from "../../primitives/select.js";
import { apiCall } from "../utils/apiCall.js";
import { flash } from "../FlashMessages.js";
import { Page, PageBody } from "../Page.js";
import { useBackendChrome } from "../BackendChromeProvider.js";
import { useConfirmDialog } from "../confirm-dialog/index.js";
import { useGuardedMutation } from "../injection/useGuardedMutation.js";
import {
  applyCustomizationDraft,
  applyItemOrder,
  cloneSidebarGroups,
  collectSidebarDefaults,
  filterMainSidebarGroups,
  mergeGroupOrder,
  resolveGroupKey,
  resolveItemKey
} from "./customization-helpers.js";
const VARIANTS_API_DEFAULT = "/api/auth/sidebar/variants";
const PREFERENCES_API_DEFAULT = "/api/auth/sidebar/preferences";
const REFRESH_SIDEBAR_EVENT = "om:refresh-sidebar";
const NEW_VARIANT_KEY = "__new__";
function formatVariantApiError(call, t) {
  const detail = call.result?.error;
  if (typeof detail === "string" && detail.length > 0 && call.status >= 400 && call.status < 500) {
    return detail;
  }
  if (typeof detail === "string" && detail.length > 0) {
    return `${t("appShell.sidebarCustomizationSaveError")} (${call.status}: ${detail})`;
  }
  return `${t("appShell.sidebarCustomizationSaveError")} (${call.status})`;
}
function findItemByKey(items, targetKey) {
  for (const item of items) {
    if (resolveItemKey(item) === targetKey) return item;
    if (item.children && item.children.length > 0) {
      const found = findItemByKey(item.children, targetKey);
      if (found) return found;
    }
  }
  return null;
}
function collectDescendantKeys(item) {
  const out = [];
  const walk = (node) => {
    if (!node.children) return;
    for (const child of node.children) {
      out.push(resolveItemKey(child));
      walk(child);
    }
  };
  walk(item);
  return out;
}
function parseDraftFromSettings(rawSettings, baseSnapshot) {
  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 responseItemOrder = {};
  if (rawSettings?.itemOrder && typeof rawSettings.itemOrder === "object") {
    for (const [groupKey, list] of Object.entries(rawSettings.itemOrder)) {
      if (!Array.isArray(list)) continue;
      const trimmedGroup = groupKey.trim();
      if (!trimmedGroup) continue;
      const seen = /* @__PURE__ */ new Set();
      const values = [];
      for (const itemKey of list) {
        if (typeof itemKey !== "string") continue;
        const trimmedItem = itemKey.trim();
        if (!trimmedItem || seen.has(trimmedItem)) continue;
        seen.add(trimmedItem);
        values.push(trimmedItem);
      }
      if (values.length > 0) responseItemOrder[trimmedGroup] = values;
    }
  }
  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;
  }
  return {
    order,
    groupLabels: responseGroupLabels,
    itemLabels: responseItemLabels,
    hiddenItemIds,
    itemOrder: responseItemOrder
  };
}
function emptyDraftFor(baseSnapshot) {
  return {
    order: baseSnapshot.map((group) => resolveGroupKey(group)),
    groupLabels: {},
    itemLabels: {},
    hiddenItemIds: {},
    itemOrder: {}
  };
}
function SidebarCustomizationEditor({
  onSaved,
  onCanceled,
  variantsApiPath = VARIANTS_API_DEFAULT,
  preferencesApiPath = PREFERENCES_API_DEFAULT,
  groups: groupsProp
}) {
  const t = useT();
  const locale = useLocale();
  const localeLabel = (locale || "").toUpperCase();
  const { payload: chromePayload, isLoading: chromeIsLoading } = useBackendChrome();
  const groupsFromChrome = chromePayload?.groups;
  const sourceGroups = groupsProp ?? groupsFromChrome ?? [];
  const { confirm: confirmDialog, ConfirmDialogElement } = useConfirmDialog();
  const [loading, setLoading] = React.useState(true);
  const [saving, setSaving] = React.useState(false);
  const [deleting, setDeleting] = React.useState(false);
  const [error, setError] = React.useState(null);
  const [variants, setVariants] = React.useState([]);
  const [selectedVariantId, setSelectedVariantId] = React.useState(null);
  const [variantName, setVariantName] = React.useState("");
  const [draft, setDraft] = React.useState(null);
  const [previewGroups, setPreviewGroups] = React.useState([]);
  const [dirty, setDirty] = React.useState(false);
  const [availableRoleTargets, setAvailableRoleTargets] = React.useState([]);
  const [selectedRoleIds, setSelectedRoleIds] = React.useState([]);
  const [canApplyToRoles, setCanApplyToRoles] = React.useState(false);
  const [addDialogOpen, setAddDialogOpen] = React.useState(false);
  const [addDialogName, setAddDialogName] = React.useState("");
  const [addDialogError, setAddDialogError] = React.useState(null);
  const baseSnapshotRef = React.useRef(null);
  const hasInitializedRef = React.useRef(false);
  const { runMutation, retryLastMutation } = useGuardedMutation({
    contextId: "sidebar-customization",
    blockedMessage: t("appShell.sidebarCustomizationSaveError")
  });
  const buildMutationContext = React.useCallback(
    (operation, variantId) => ({
      formId: "sidebar-customization",
      variantId: variantId ?? null,
      operation,
      retryLastMutation
    }),
    [retryLastMutation]
  );
  const isNewVariant = selectedVariantId === null;
  const selectedVariant = React.useMemo(
    () => selectedVariantId ? variants.find((v) => v.id === selectedVariantId) ?? null : null,
    [selectedVariantId, variants]
  );
  const updateDraft = React.useCallback((updater) => {
    setDraft((prev) => {
      if (!prev) return prev;
      const next = updater(prev);
      if (baseSnapshotRef.current) {
        setPreviewGroups(applyCustomizationDraft(baseSnapshotRef.current, next));
      }
      return next;
    });
    setDirty(true);
  }, []);
  const buildBaseSnapshot = React.useCallback(() => {
    return filterMainSidebarGroups(cloneSidebarGroups(sourceGroups));
  }, [sourceGroups]);
  const loadVariantsList = React.useCallback(async () => {
    const url = `${variantsApiPath}?_=${Date.now()}`;
    const call = await apiCall(url, { cache: "no-store" });
    if (!call.ok) {
      throw new Error("list-failed");
    }
    return call.result?.variants ?? [];
  }, [variantsApiPath]);
  const loadRolesPayload = React.useCallback(async () => {
    const call = await apiCall(preferencesApiPath);
    if (!call.ok) {
      return { canApplyToRoles: false, roles: [] };
    }
    const data = call.result ?? null;
    const can = data?.canApplyToRoles === true;
    const roles = Array.isArray(data?.roles) ? data.roles.filter((r) => typeof r?.id === "string" && typeof r?.name === "string").map((r) => ({ id: r.id, name: r.name, hasPreference: r.hasPreference === true })) : [];
    return { canApplyToRoles: can, roles };
  }, [preferencesApiPath]);
  const selectVariantInternal = React.useCallback((variant, list) => {
    const baseSnapshot = baseSnapshotRef.current ?? buildBaseSnapshot();
    baseSnapshotRef.current = baseSnapshot;
    if (variant) {
      const initialDraft = parseDraftFromSettings(variant.settings, baseSnapshot);
      setSelectedVariantId(variant.id);
      setVariantName(variant.name);
      setDraft(initialDraft);
      setPreviewGroups(applyCustomizationDraft(baseSnapshot, initialDraft));
    } else {
      const empty = emptyDraftFor(baseSnapshot);
      setSelectedVariantId(null);
      const usedNumbers = /* @__PURE__ */ new Set();
      for (const v of list) {
        if (v.name === "My preferences") usedNumbers.add(1);
        const match = v.name.match(/^My preferences\s+(\d+)$/);
        if (match) usedNumbers.add(Number.parseInt(match[1], 10));
      }
      let next = 1;
      while (usedNumbers.has(next)) next += 1;
      const suggestion = next === 1 ? "My preferences" : `My preferences ${next}`;
      setVariantName(suggestion);
      setDraft(empty);
      setPreviewGroups(applyCustomizationDraft(baseSnapshot, empty));
    }
    setDirty(false);
  }, [buildBaseSnapshot]);
  React.useEffect(() => {
    if (hasInitializedRef.current) return;
    if (sourceGroups.length === 0) return;
    hasInitializedRef.current = true;
    async function init() {
      setLoading(true);
      setError(null);
      try {
        const [list, rolesPayload] = await Promise.all([
          loadVariantsList(),
          loadRolesPayload()
        ]);
        setVariants(list);
        setCanApplyToRoles(rolesPayload.canApplyToRoles);
        setAvailableRoleTargets(rolesPayload.roles);
        const active = list.find((v) => v.isActive);
        const initial = active ?? list[0] ?? null;
        selectVariantInternal(initial, list);
        setSelectedRoleIds([]);
      } catch (err) {
        console.error("Failed to load sidebar variants", err);
        setError(t("appShell.sidebarCustomizationLoadError"));
      } finally {
        setLoading(false);
      }
    }
    void init();
  }, [sourceGroups.length]);
  const toggleRoleSelection = React.useCallback((roleId) => {
    setSelectedRoleIds((prev) => prev.includes(roleId) ? prev.filter((id) => id !== roleId) : [...prev, roleId]);
    setDirty(true);
  }, []);
  const createNewVariant = React.useCallback(async (proposedName, options = {}) => {
    if (saving || deleting) return { ok: false };
    if (dirty && selectedVariantId !== null) {
      const proceed = await confirmDialog({
        title: t("appShell.sidebarCustomizationSwitchConfirmTitle", "Discard unsaved changes?"),
        text: t("appShell.sidebarCustomizationSwitchConfirmText", "You have unsaved changes for the current variant. Switching will discard them."),
        confirmText: t("appShell.sidebarCustomizationSwitchConfirmYes", "Discard and switch"),
        cancelText: t("common.cancel", "Cancel"),
        variant: "destructive"
      });
      if (!proceed) return { ok: false };
    }
    setSaving(true);
    if (!options.suppressPageError) setError(null);
    try {
      const baseSnapshot = baseSnapshotRef.current ?? buildBaseSnapshot();
      baseSnapshotRef.current = baseSnapshot;
      const groupOrder = baseSnapshot.map((g) => resolveGroupKey(g));
      const trimmed = (proposedName ?? "").trim();
      const call = await runMutation({
        operation: () => apiCall(variantsApiPath, {
          method: "POST",
          headers: { "content-type": "application/json" },
          body: JSON.stringify({
            // If name is omitted, server auto-names ("My preferences", "My preferences 2", …).
            name: trimmed.length > 0 ? trimmed : void 0,
            settings: { groupOrder, groupLabels: {}, itemLabels: {}, hiddenItems: [], itemOrder: {} },
            isActive: true
          })
        }),
        context: buildMutationContext("createVariant"),
        mutationPayload: { name: trimmed.length > 0 ? trimmed : null }
      });
      if (!call.ok) {
        const message = formatVariantApiError(call, t);
        if (!options.suppressPageError) setError(message);
        return { ok: false, error: message };
      }
      const created = call.result?.variant ?? null;
      let nextList;
      try {
        nextList = await loadVariantsList();
      } catch {
        nextList = variants;
      }
      if (created && !nextList.some((v) => v.id === created.id)) {
        nextList = [...nextList, created];
      }
      setVariants(nextList);
      if (created) {
        const fresh = nextList.find((v) => v.id === created.id) ?? created;
        selectVariantInternal(fresh, nextList);
      }
      flash(t("appShell.sidebarCustomizationVariantCreated", "Variant created."), "success");
      return { ok: true };
    } catch (err) {
      console.error("Failed to create sidebar variant", err);
      const message = t("appShell.sidebarCustomizationSaveError");
      if (!options.suppressPageError) setError(message);
      return { ok: false, error: message };
    } finally {
      setSaving(false);
    }
  }, [saving, deleting, dirty, selectedVariantId, confirmDialog, t, buildBaseSnapshot, variantsApiPath, loadVariantsList, selectVariantInternal, variants, runMutation, buildMutationContext]);
  const handleVariantSwitch = React.useCallback(async (key) => {
    if (saving || deleting) return;
    if (key === selectedVariantId) return;
    if (key === NEW_VARIANT_KEY && isNewVariant) return;
    if (dirty) {
      const proceed = await confirmDialog({
        title: t("appShell.sidebarCustomizationSwitchConfirmTitle", "Discard unsaved changes?"),
        text: t("appShell.sidebarCustomizationSwitchConfirmText", "You have unsaved changes for the current variant. Switching will discard them."),
        confirmText: t("appShell.sidebarCustomizationSwitchConfirmYes", "Discard and switch"),
        cancelText: t("common.cancel", "Cancel"),
        variant: "destructive"
      });
      if (!proceed) return;
    }
    if (key === NEW_VARIANT_KEY) {
      selectVariantInternal(null, variants);
      return;
    }
    const next = variants.find((v) => v.id === key) ?? null;
    selectVariantInternal(next, variants);
  }, [saving, deleting, selectedVariantId, isNewVariant, dirty, confirmDialog, t, variants, selectVariantInternal]);
  const moveGroup = React.useCallback((groupId, offset) => {
    updateDraft((draft2) => {
      const order = [...draft2.order];
      const index = order.indexOf(groupId);
      if (index === -1) return draft2;
      const nextIndex = Math.max(0, Math.min(order.length - 1, index + offset));
      if (nextIndex === index) return draft2;
      order.splice(index, 1);
      order.splice(nextIndex, 0, groupId);
      return { ...draft2, order };
    });
  }, [updateDraft]);
  const dndSensors = useSensors(
    useSensor(PointerSensor, { activationConstraint: { distance: 4 } }),
    useSensor(KeyboardSensor)
  );
  const handleItemDragEnd = React.useCallback((groupKey, currentItemKeys) => (event) => {
    const { active, over } = event;
    if (!over || active.id === over.id) return;
    const fromId = String(active.id);
    const toId = String(over.id);
    updateDraft((draft2) => {
      const baseOrder = draft2.itemOrder?.[groupKey]?.length ? [...draft2.itemOrder[groupKey]] : [...currentItemKeys];
      const fromIndex = baseOrder.indexOf(fromId);
      const toIndex = baseOrder.indexOf(toId);
      if (fromIndex === -1 || toIndex === -1) return draft2;
      const nextOrder = arrayMove(baseOrder, fromIndex, toIndex);
      return {
        ...draft2,
        itemOrder: { ...draft2.itemOrder ?? {}, [groupKey]: nextOrder }
      };
    });
  }, [updateDraft]);
  const setGroupLabel = React.useCallback((groupId, value) => {
    updateDraft((draft2) => {
      const next = { ...draft2.groupLabels };
      if (value.trim().length === 0) delete next[groupId];
      else next[groupId] = value;
      return { ...draft2, groupLabels: next };
    });
  }, [updateDraft]);
  const setItemLabel = React.useCallback((itemId, value) => {
    updateDraft((draft2) => {
      const next = { ...draft2.itemLabels };
      if (value.trim().length === 0) delete next[itemId];
      else next[itemId] = value;
      return { ...draft2, itemLabels: next };
    });
  }, [updateDraft]);
  const setItemHidden = React.useCallback((itemId, hidden) => {
    updateDraft((draft2) => {
      const next = { ...draft2.hiddenItemIds };
      const apply = (id) => {
        if (hidden) next[id] = true;
        else delete next[id];
      };
      apply(itemId);
      if (baseSnapshotRef.current) {
        for (const group of baseSnapshotRef.current) {
          const target = findItemByKey(group.items, itemId);
          if (!target) continue;
          for (const descendantKey of collectDescendantKeys(target)) apply(descendantKey);
          break;
        }
      }
      return { ...draft2, hiddenItemIds: next };
    });
  }, [updateDraft]);
  const reset = React.useCallback(() => {
    if (!baseSnapshotRef.current) return;
    if (selectedVariant) {
      const initialDraft = parseDraftFromSettings(selectedVariant.settings, baseSnapshotRef.current);
      setDraft(initialDraft);
      setPreviewGroups(applyCustomizationDraft(baseSnapshotRef.current, initialDraft));
    } else {
      const empty = emptyDraftFor(baseSnapshotRef.current);
      setDraft(empty);
      setPreviewGroups(applyCustomizationDraft(baseSnapshotRef.current, empty));
    }
    setDirty(false);
  }, [selectedVariant]);
  const cancel = React.useCallback(() => {
    onCanceled?.();
  }, [onCanceled]);
  const submitAddDialog = React.useCallback(async () => {
    setAddDialogError(null);
    const result = await createNewVariant(addDialogName, { suppressPageError: true });
    if (result.ok) {
      setAddDialogOpen(false);
      setAddDialogName("");
      setAddDialogError(null);
      return;
    }
    setAddDialogError(result.error ?? t("appShell.sidebarCustomizationSaveError"));
  }, [createNewVariant, addDialogName, t]);
  const sanitizeSettingsPayload = React.useCallback(() => {
    if (!draft || !baseSnapshotRef.current) return null;
    const baseGroups = baseSnapshotRef.current;
    const { groupDefaults, itemDefaults } = collectSidebarDefaults(baseGroups);
    const sanitizedGroupLabels = {};
    for (const [key, value] of Object.entries(draft.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(draft.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(draft.hiddenItemIds)) {
      if (!hidden) continue;
      if (!itemDefaults.has(itemId)) continue;
      sanitizedHiddenItems.push(itemId);
    }
    const groupKeys = /* @__PURE__ */ new Set();
    for (const group of baseGroups) groupKeys.add(resolveGroupKey(group));
    const sanitizedItemOrder = {};
    for (const [groupKey, list] of Object.entries(draft.itemOrder ?? {})) {
      if (!groupKeys.has(groupKey)) continue;
      const seen = /* @__PURE__ */ new Set();
      const values = [];
      for (const itemKey of list) {
        if (seen.has(itemKey)) continue;
        if (!itemDefaults.has(itemKey)) continue;
        seen.add(itemKey);
        values.push(itemKey);
      }
      if (values.length > 0) sanitizedItemOrder[groupKey] = values;
    }
    return {
      groupOrder: draft.order,
      groupLabels: sanitizedGroupLabels,
      itemLabels: sanitizedItemLabels,
      hiddenItems: sanitizedHiddenItems,
      itemOrder: sanitizedItemOrder
    };
  }, [draft]);
  const save = React.useCallback(async () => {
    const settings = sanitizeSettingsPayload();
    if (!settings) return;
    setSaving(true);
    setError(null);
    try {
      const trimmedName = variantName.trim();
      const isCurrentlyActive = selectedVariant?.isActive ?? false;
      let savedVariant = null;
      if (isNewVariant) {
        const call = await runMutation({
          operation: () => apiCall(variantsApiPath, {
            method: "POST",
            headers: { "content-type": "application/json" },
            body: JSON.stringify({
              name: trimmedName.length > 0 ? trimmedName : void 0,
              settings,
              // New variants are activated by default — there's only one active per scope,
              // others get auto-deactivated server-side.
              isActive: true
            })
          }),
          context: buildMutationContext("saveVariant"),
          mutationPayload: { name: trimmedName.length > 0 ? trimmedName : null, isActive: true }
        });
        if (!call.ok) {
          setError(formatVariantApiError(call, t));
          return;
        }
        savedVariant = call.result?.variant ?? null;
      } else if (selectedVariantId) {
        const call = await runMutation({
          operation: () => apiCall(`${variantsApiPath}/${encodeURIComponent(selectedVariantId)}`, {
            method: "PUT",
            headers: { "content-type": "application/json" },
            body: JSON.stringify({
              name: trimmedName.length > 0 ? trimmedName : void 0,
              settings,
              isActive: isCurrentlyActive
            })
          }),
          context: buildMutationContext("saveVariant", selectedVariantId),
          mutationPayload: {
            id: selectedVariantId,
            name: trimmedName.length > 0 ? trimmedName : null,
            isActive: isCurrentlyActive
          }
        });
        if (!call.ok) {
          setError(formatVariantApiError(call, t));
          return;
        }
        savedVariant = call.result?.variant ?? null;
      }
      const preferencesPayload = {
        groupOrder: settings.groupOrder,
        groupLabels: settings.groupLabels,
        itemLabels: settings.itemLabels,
        hiddenItems: settings.hiddenItems,
        itemOrder: settings.itemOrder
      };
      if (canApplyToRoles) {
        const applyToRolesPayload = [...selectedRoleIds];
        const clearRoleIdsPayload = availableRoleTargets.filter((role) => role.hasPreference && !selectedRoleIds.includes(role.id)).map((role) => role.id);
        preferencesPayload.applyToRoles = applyToRolesPayload;
        preferencesPayload.clearRoleIds = clearRoleIdsPayload;
      }
      const preferencesCall = await runMutation({
        operation: () => apiCall(preferencesApiPath, {
          method: "PUT",
          headers: { "content-type": "application/json" },
          body: JSON.stringify(preferencesPayload)
        }),
        context: buildMutationContext("savePreferences", selectedVariantId),
        mutationPayload: preferencesPayload
      });
      if (!preferencesCall.ok) {
        setError(formatVariantApiError(preferencesCall, t));
        return;
      }
      try {
        window.dispatchEvent(new Event(REFRESH_SIDEBAR_EVENT));
      } catch {
      }
      const [list, rolesPayload] = await Promise.all([
        loadVariantsList(),
        loadRolesPayload()
      ]);
      const mergedList = savedVariant && !list.some((v) => v.id === savedVariant.id) ? [...list, savedVariant] : list;
      setVariants(mergedList);
      setCanApplyToRoles(rolesPayload.canApplyToRoles);
      setAvailableRoleTargets(rolesPayload.roles);
      if (savedVariant) {
        const fresh = mergedList.find((v) => v.id === savedVariant.id) ?? savedVariant;
        selectVariantInternal(fresh, mergedList);
      } else {
        const active = mergedList.find((v) => v.isActive) ?? mergedList[0] ?? null;
        selectVariantInternal(active, mergedList);
      }
      flash(
        isNewVariant ? t("appShell.sidebarCustomizationVariantCreated", "Variant created.") : t("appShell.sidebarCustomizationVariantSaved", "Variant saved."),
        "success"
      );
      onSaved?.();
    } catch (err) {
      console.error("Failed to save sidebar variant", err);
      setError(t("appShell.sidebarCustomizationSaveError"));
    } finally {
      setSaving(false);
    }
  }, [draft, variantName, isNewVariant, selectedVariant, selectedVariantId, variantsApiPath, preferencesApiPath, canApplyToRoles, selectedRoleIds, availableRoleTargets, t, sanitizeSettingsPayload, loadVariantsList, loadRolesPayload, selectVariantInternal, onSaved, runMutation, buildMutationContext]);
  const toggleActive = React.useCallback(async (next) => {
    if (!selectedVariant || saving || deleting) return;
    setError(null);
    try {
      const call = await runMutation({
        operation: () => apiCall(`${variantsApiPath}/${encodeURIComponent(selectedVariant.id)}`, {
          method: "PUT",
          headers: { "content-type": "application/json" },
          body: JSON.stringify({ isActive: next })
        }),
        context: buildMutationContext("toggleVariantActive", selectedVariant.id),
        mutationPayload: { id: selectedVariant.id, isActive: next }
      });
      if (!call.ok) {
        setError(t("appShell.sidebarCustomizationSaveError"));
        return;
      }
      try {
        window.dispatchEvent(new Event(REFRESH_SIDEBAR_EVENT));
      } catch {
      }
      const list = await loadVariantsList();
      setVariants(list);
      const fresh = list.find((v) => v.id === selectedVariant.id) ?? selectedVariant;
      selectVariantInternal(fresh, list);
    } catch (err) {
      console.error("Failed to toggle variant active state", err);
      setError(t("appShell.sidebarCustomizationSaveError"));
    }
  }, [selectedVariant, saving, deleting, variantsApiPath, t, loadVariantsList, selectVariantInternal, runMutation, buildMutationContext]);
  const deleteVariant = React.useCallback(async () => {
    if (!selectedVariant) return;
    const proceed = await confirmDialog({
      title: t("appShell.sidebarCustomizationDeleteVariantTitle", "Delete variant?"),
      text: t(
        "appShell.sidebarCustomizationDeleteVariantText",
        "This variant will be removed from your library."
      ),
      confirmText: t("appShell.sidebarCustomizationDeleteVariantConfirm", "Delete variant"),
      cancelText: t("common.cancel", "Cancel"),
      variant: "destructive"
    });
    if (!proceed) return;
    setDeleting(true);
    setError(null);
    try {
      const call = await runMutation({
        operation: () => apiCall(`${variantsApiPath}/${encodeURIComponent(selectedVariant.id)}`, { method: "DELETE" }),
        context: buildMutationContext("deleteVariant", selectedVariant.id),
        mutationPayload: { id: selectedVariant.id }
      });
      if (!call.ok) {
        setError(t("appShell.sidebarCustomizationSaveError"));
        return;
      }
      try {
        window.dispatchEvent(new Event(REFRESH_SIDEBAR_EVENT));
      } catch {
      }
      const list = await loadVariantsList();
      setVariants(list);
      const fallback = list[0] ?? null;
      selectVariantInternal(fallback, list);
    } catch (err) {
      console.error("Failed to delete variant", err);
      setError(t("appShell.sidebarCustomizationSaveError"));
    } finally {
      setDeleting(false);
    }
  }, [selectedVariant, confirmDialog, t, variantsApiPath, loadVariantsList, selectVariantInternal, runMutation, buildMutationContext]);
  const isBusy = saving || deleting;
  if (loading && !draft) {
    return /* @__PURE__ */ jsxs(Fragment, { children: [
      ConfirmDialogElement,
      /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
        /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
          /* @__PURE__ */ jsx("div", { className: "h-7 w-64 animate-pulse rounded bg-muted" }),
          /* @__PURE__ */ jsx("div", { className: "h-4 w-96 animate-pulse rounded bg-muted/60" })
        ] }),
        /* @__PURE__ */ jsx("div", { className: "h-64 animate-pulse rounded-lg border bg-muted/30" })
      ] })
    ] });
  }
  if (!draft || !baseSnapshotRef.current) {
    const stillLoading = loading || chromeIsLoading || sourceGroups.length === 0;
    return /* @__PURE__ */ jsxs(Fragment, { children: [
      ConfirmDialogElement,
      /* @__PURE__ */ jsx("div", { className: "rounded-lg border border-dashed bg-muted/30 p-6 text-sm text-muted-foreground", children: stillLoading ? t("appShell.sidebarCustomizationLoading", "Loading\u2026") : error ?? t("appShell.sidebarCustomizationLoadError") })
    ] });
  }
  const baseGroupsForDefaults = baseSnapshotRef.current;
  const baseGroupMap = /* @__PURE__ */ new Map();
  for (const group of baseGroupsForDefaults) {
    baseGroupMap.set(resolveGroupKey(group), group);
  }
  const orderedGroupIds = mergeGroupOrder(draft.order, Array.from(baseGroupMap.keys()));
  const totalGroups = orderedGroupIds.length;
  const selectValue = isNewVariant ? NEW_VARIANT_KEY : selectedVariantId ?? NEW_VARIANT_KEY;
  const showVariantPicker = variants.length > 0 || isNewVariant;
  return /* @__PURE__ */ jsxs(Fragment, { children: [
    ConfirmDialogElement,
    /* @__PURE__ */ jsx(
      Dialog,
      {
        open: addDialogOpen,
        onOpenChange: (next) => {
          if (!next) {
            setAddDialogOpen(false);
            setAddDialogName("");
            setAddDialogError(null);
          }
        },
        children: /* @__PURE__ */ jsxs(DialogContent, { className: "sm:max-w-md", children: [
          /* @__PURE__ */ jsxs(DialogHeader, { children: [
            /* @__PURE__ */ jsx(DialogTitle, { children: t("appShell.sidebarCustomizationAddDialogTitle", "Add new variant") }),
            /* @__PURE__ */ jsx(DialogDescription, { children: t("appShell.sidebarCustomizationAddDialogDescription", "Choose a name for the new sidebar variant. Leave blank to auto-name it.") })
          ] }),
          /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5", children: [
            /* @__PURE__ */ jsx("label", { className: "text-xs font-medium uppercase tracking-wider text-muted-foreground/70", children: t("appShell.sidebarCustomizationVariantNameLabel", "Variant name") }),
            /* @__PURE__ */ jsx(
              Input,
              {
                autoFocus: true,
                value: addDialogName,
                onChange: (event) => {
                  setAddDialogName(event.target.value);
                  if (addDialogError) setAddDialogError(null);
                },
                onKeyDown: (event) => {
                  if (event.key === "Enter" && !event.shiftKey) {
                    event.preventDefault();
                    void submitAddDialog();
                  }
                },
                placeholder: t("appShell.sidebarCustomizationVariantNamePlaceholder", "My preferences"),
                disabled: saving,
                "aria-invalid": addDialogError ? true : void 0,
                "aria-describedby": addDialogError ? "sidebar-add-variant-error" : void 0
              }
            ),
            addDialogError ? /* @__PURE__ */ jsx(
              "p",
              {
                id: "sidebar-add-variant-error",
                role: "alert",
                className: "text-xs text-destructive",
                children: addDialogError
              }
            ) : null
          ] }),
          /* @__PURE__ */ jsxs(DialogFooter, { className: "mt-2", children: [
            /* @__PURE__ */ jsx(
              Button,
              {
                type: "button",
                variant: "outline",
                onClick: () => {
                  setAddDialogOpen(false);
                  setAddDialogName("");
                  setAddDialogError(null);
                },
                disabled: saving,
                children: t("appShell.sidebarCustomizationCancel")
              }
            ),
            /* @__PURE__ */ jsx(
              Button,
              {
                type: "button",
                onClick: () => {
                  void submitAddDialog();
                },
                disabled: saving,
                children: saving ? t("appShell.sidebarCustomizationCreating", "Creating\u2026") : t("appShell.sidebarCustomizationCreateVariant", "Create variant")
              }
            )
          ] })
        ] })
      }
    ),
    /* @__PURE__ */ jsxs(Page, { children: [
      /* @__PURE__ */ jsxs("header", { className: "space-y-1", children: [
        /* @__PURE__ */ jsx("h1", { className: "text-xl sm:text-2xl font-semibold leading-tight", children: t("appShell.sidebarCustomizationHeading") }),
        /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: t("appShell.sidebarCustomizationHint", { locale: localeLabel }) })
      ] }),
      error ? /* @__PURE__ */ jsx("div", { className: "rounded-lg border border-destructive/40 bg-destructive/5 px-4 py-3 text-sm text-destructive", children: error }) : null,
      /* @__PURE__ */ jsxs(PageBody, { className: "grid grid-cols-1 gap-6 lg:grid-cols-[minmax(0,1fr)_minmax(0,360px)]", children: [
        /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
          (() => {
            const showRolesCard = canApplyToRoles && availableRoleTargets.length > 0;
            if (!showVariantPicker && !showRolesCard) return null;
            return /* @__PURE__ */ jsx(Card, { children: /* @__PURE__ */ jsxs(CardContent, { className: "flex flex-col gap-6", children: [
              showVariantPicker ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4", children: [
                /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5", children: [
                  /* @__PURE__ */ jsx("label", { className: "text-xs font-medium uppercase tracking-wider text-muted-foreground/70", children: t("appShell.sidebarCustomizationVariantNameLabel", "Variant name") }),
                  /* @__PURE__ */ jsxs("div", { className: "flex items-stretch gap-2", children: [
                    /* @__PURE__ */ jsxs("div", { className: "relative flex flex-1 items-stretch", children: [
                      /* @__PURE__ */ jsx(
                        Input,
                        {
                          value: variantName,
                          onChange: (event) => {
                            setVariantName(event.target.value);
                            setDirty(true);
                          },
                          placeholder: t("appShell.sidebarCustomizationVariantNamePlaceholder", "My preferences"),
                          disabled: isBusy,
                          className: "w-full pr-10"
                        }
                      ),
                      /* @__PURE__ */ jsxs(
                        Select,
                        {
                          value: selectValue,
                          onValueChange: (value) => {
                            void handleVariantSwitch(value);
                          },
                          disabled: isBusy || loading,
                          children: [
                            /* @__PURE__ */ jsx(
                              SelectTrigger,
                              {
                                className: "pointer-events-none absolute inset-0 h-full w-full justify-end border-0 bg-transparent px-3 shadow-none ring-0 focus-visible:ring-0 focus-visible:ring-offset-0 [&>span]:hidden [&>svg]:pointer-events-auto",
                                "aria-label": t("appShell.sidebarCustomizationVariantPickerLabel", "Pick variant"),
                                children: /* @__PURE__ */ jsx(SelectValue, {})
                              }
                            ),
                            /* @__PURE__ */ jsx(SelectContent, { children: variants.length > 0 ? variants.map((variant) => /* @__PURE__ */ jsx(SelectItem, { value: variant.id, children: variant.name }, variant.id)) : /* @__PURE__ */ jsx(SelectItem, { value: NEW_VARIANT_KEY, disabled: true, children: t("appShell.sidebarCustomizationVariantsEmpty", "No saved variants yet") }) })
                          ]
                        }
                      )
                    ] }),
                    /* @__PURE__ */ jsxs(
                      Button,
                      {
                        type: "button",
                        onClick: () => {
                          setAddDialogName("");
                          setAddDialogError(null);
                          setAddDialogOpen(true);
                        },
                        disabled: isBusy,
                        title: t("appShell.sidebarCustomizationVariantNew", "Add new variant"),
                        children: [
                          /* @__PURE__ */ jsx(Plus, { className: "size-4" }),
                          t("appShell.sidebarCustomizationCreateNew", "Create new")
                        ]
                      }
                    )
                  ] })
                ] }),
                isNewVariant ? /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: t("appShell.sidebarCustomizationVariantNewHint", "Saving will create a new variant. If you leave the name blank, it will be auto-named.") }) : null,
                /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
                  /* @__PURE__ */ jsx(
                    Switch,
                    {
                      checked: selectedVariant?.isActive ?? isNewVariant,
                      onCheckedChange: (next) => {
                        if (isNewVariant) return;
                        void toggleActive(next === true);
                      },
                      disabled: isBusy || isNewVariant,
                      "aria-label": t("appShell.sidebarCustomizationVariantActiveLabel", "Active")
                    }
                  ),
                  /* @__PURE__ */ jsx("span", { className: "text-xs font-medium uppercase tracking-wider text-muted-foreground/70", children: t("appShell.sidebarCustomizationVariantActiveLabel", "Active") })
                ] })
              ] }) : null,
              showVariantPicker && showRolesCard ? /* @__PURE__ */ jsx("div", { className: "-mx-6 border-t", "aria-hidden": true }) : null,
              showRolesCard ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
                /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
                  /* @__PURE__ */ jsx("h3", { className: "text-base font-semibold leading-none text-foreground", children: t("appShell.sidebarApplyToRolesTitle") }),
                  /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: t("appShell.sidebarApplyToRolesDescription") })
                ] }),
                /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-1.5 max-w-sm", children: availableRoleTargets.map((role) => {
                  const checked = selectedRoleIds.includes(role.id);
                  const willClear = role.hasPreference && !checked;
                  return /* @__PURE__ */ jsxs(
                    "label",
                    {
                      className: "flex cursor-pointer items-center gap-3 rounded-lg border bg-background px-3 py-2 text-sm transition-colors hover:bg-muted",
                      children: [
                        /* @__PURE__ */ jsx(
                          Switch,
                          {
                            checked,
                            onCheckedChange: () => toggleRoleSelection(role.id),
                            disabled: isBusy
                          }
                        ),
                        /* @__PURE__ */ jsx("span", { className: "flex-1 truncate font-medium text-foreground", children: role.name }),
                        role.hasPreference ? /* @__PURE__ */ jsxs(Tag, { variant: willClear ? "error" : "info", dot: !willClear, children: [
                          willClear ? /* @__PURE__ */ jsx(AlertTriangle, { className: "size-3", "aria-hidden": true }) : null,
                          willClear ? t("appShell.sidebarRoleWillClear") : t("appShell.sidebarRoleHasPreset")
                        ] }) : null
                      ]
                    },
                    role.id
                  );
                }) })
              ] }) : null,
              /* @__PURE__ */ jsx("div", { className: "-mx-6 border-t", "aria-hidden": true }),
              /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3", children: [
                selectedVariant ? /* @__PURE__ */ jsxs(
                  Button,
                  {
                    type: "button",
                    variant: "outline",
                    onClick: () => {
                      void deleteVariant();
                    },
                    disabled: isBusy,
                    className: "text-destructive hover:text-destructive",
                    children: [
                      /* @__PURE__ */ jsx(Trash2, { className: "size-4" }),
                      deleting ? t("appShell.sidebarCustomizationDeleteVariantInProgress", "Deleting\u2026") : t("appShell.sidebarCustomizationDeleteVariant", "Delete variant")
                    ]
                  }
                ) : /* @__PURE__ */ jsx("span", {}),
                /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
                  /* @__PURE__ */ jsx(
                    Button,
                    {
                      type: "button",
                      variant: "ghost",
                      onClick: reset,
                      disabled: isBusy || !dirty,
                      children: t("appShell.sidebarCustomizationReset")
                    }
                  ),
                  /* @__PURE__ */ jsx(
                    Button,
                    {
                      type: "button",
                      variant: "outline",
                      onClick: cancel,
                      disabled: isBusy || !dirty,
                      children: t("appShell.sidebarCustomizationCancel")
                    }
                  ),
                  /* @__PURE__ */ jsx(
                    Button,
                    {
                      type: "button",
                      onClick: save,
                      disabled: isBusy || !isNewVariant && !dirty,
                      children: saving ? isNewVariant ? t("appShell.sidebarCustomizationCreating", "Creating\u2026") : t("appShell.sidebarCustomizationSaving") : isNewVariant ? t("appShell.sidebarCustomizationCreateVariant", "Create variant") : t("appShell.sidebarCustomizationSave")
                    }
                  )
                ] })
              ] })
            ] }) });
          })(),
          /* @__PURE__ */ jsxs(Card, { children: [
            /* @__PURE__ */ jsxs(CardHeader, { children: [
              /* @__PURE__ */ jsx(CardTitle, { className: "text-base", children: t("appShell.sidebarCustomizationOrderHeading", "Order & visibility") }),
              /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: t("appShell.sidebarCustomizationOrderDescription", "Reorder groups, rename them, and toggle individual items on or off.") })
            ] }),
            /* @__PURE__ */ jsx(CardContent, { className: "space-y-3", children: orderedGroupIds.map((groupId, index) => {
              const baseGroup = baseGroupMap.get(groupId);
              if (!baseGroup) return null;
              const placeholder = baseGroup.defaultName ?? baseGroup.name;
              const value = draft.groupLabels[groupId] ?? "";
              const trimmedValue = value.trim();
              const isGroupModified = trimmedValue.length > 0 && trimmedValue !== placeholder;
              return /* @__PURE__ */ jsxs("div", { className: "rounded-lg border bg-background", children: [
                /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-3 border-b px-4 py-3", children: [
                  /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col gap-1.5", children: [
                    /* @__PURE__ */ jsx("label", { className: "text-xs font-medium uppercase tracking-wider text-muted-foreground/70", children: t("appShell.sidebarCustomizationGroupLabel") }),
                    /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
                      /* @__PURE__ */ jsx(
                        Input,
                        {
                          value,
                          onChange: (event) => setGroupLabel(groupId, event.target.value),
                          placeholder,
                          disabled: isBusy,
                          className: "flex-1"
                        }
                      ),
                      isGroupModified ? /* @__PURE__ */ jsx(
                        IconButton,
                        {
                          type: "button",
                          variant: "ghost",
                          size: "sm",
                          onClick: () => setGroupLabel(groupId, ""),
                          disabled: isBusy,
                          "aria-label": t("appShell.sidebarCustomizationResetField", "Reset to default"),
                          title: t("appShell.sidebarCustomizationResetField", "Reset to default"),
                          children: /* @__PURE__ */ jsx(RotateCcw, { className: "size-3.5" })
                        }
                      ) : null
                    ] }),
                    isGroupModified ? /* @__PURE__ */ jsxs("p", { className: "text-xs text-muted-foreground", children: [
                      t("appShell.sidebarCustomizationDefault", "Default:"),
                      " ",
                      /* @__PURE__ */ jsx("span", { className: "font-medium text-foreground/80", children: placeholder })
                    ] }) : null
                  ] }),
                  /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-1 mt-[26px]", children: [
                    /* @__PURE__ */ jsx(
                      IconButton,
                      {
                        type: "button",
                        variant: "outline",
                        size: "sm",
                        className: "text-muted-foreground hover:text-foreground",
                        onClick: () => moveGroup(groupId, -1),
                        disabled: index === 0 || isBusy,
                        "aria-label": t("appShell.sidebarCustomizationMoveUp"),
                        title: t("appShell.sidebarCustomizationMoveUp"),
                        children: /* @__PURE__ */ jsx(ChevronUp, { className: "size-4" })
                      }
                    ),
                    /* @__PURE__ */ jsx(
                      IconButton,
                      {
                        type: "button",
                        variant: "outline",
                        size: "sm",
                        className: "text-muted-foreground hover:text-foreground",
                        onClick: () => moveGroup(groupId, 1),
                        disabled: index === totalGroups - 1 || isBusy,
                        "aria-label": t("appShell.sidebarCustomizationMoveDown"),
                        title: t("appShell.sidebarCustomizationMoveDown"),
                        children: /* @__PURE__ */ jsx(ChevronDown, { className: "size-4" })
                      }
                    )
                  ] })
                ] }),
                /* @__PURE__ */ jsx("div", { className: "flex flex-col divide-y", children: /* @__PURE__ */ jsx(
                  ItemRows,
                  {
                    items: baseGroup.items,
                    draft,
                    saving: isBusy,
                    onLabelChange: setItemLabel,
                    onHiddenChange: setItemHidden,
                    t,
                    groupKey: groupId,
                    sensors: dndSensors,
                    onDragEnd: handleItemDragEnd(groupId, baseGroup.items.map((item) => resolveItemKey(item)))
                  }
                ) })
              ] }, groupId);
            }) })
          ] })
        ] }),
        /* @__PURE__ */ jsx("aside", { className: "hidden lg:block", children: /* @__PURE__ */ jsx("div", { className: "sticky top-6", children: /* @__PURE__ */ jsxs("div", { className: "relative", children: [
          /* @__PURE__ */ jsx("span", { className: "absolute left-1/2 top-0 z-10 -translate-x-1/2 -translate-y-1/2 rounded-md bg-accent-indigo px-3 py-1 text-xs font-semibold uppercase tracking-wider text-accent-indigo-foreground shadow-sm", children: t("appShell.sidebarCustomizationPreview", "Preview") }),
          /* @__PURE__ */ jsx(
            SidebarPreview,
            {
              groups: previewGroups,
              productName: t("appShell.productName", "Open Mercato"),
              pickFirstActive: true
            }
          )
        ] }) }) })
      ] })
    ] })
  ] });
}
function ItemRow({ item, draft, saving, onLabelChange, onHiddenChange, t, depth, dragHandle, ancestorHidden = false }) {
  const itemKey = resolveItemKey(item);
  const placeholder = item.defaultTitle ?? item.title;
  const value = draft.itemLabels[itemKey] ?? "";
  const trimmedValue = value.trim();
  const isModified = trimmedValue.length > 0 && trimmedValue !== placeholder;
  const hidden = draft.hiddenItemIds[itemKey] === true;
  const effectivelyDimmed = hidden || ancestorHidden;
  return /* @__PURE__ */ jsxs(
    "div",
    {
      className: "flex items-start gap-3 px-4 py-3 transition-colors hover:bg-muted/40",
      style: depth ? { paddingLeft: 16 + depth * 24 } : void 0,
      children: [
        dragHandle ?? (depth > 0 ? /* @__PURE__ */ jsx("span", { className: "w-4 shrink-0", "aria-hidden": true }) : null),
        /* @__PURE__ */ jsxs("div", { className: `min-w-0 flex-1 flex flex-col gap-1.5 ${effectivelyDimmed ? "opacity-60" : ""}`, children: [
          /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
            /* @__PURE__ */ jsx("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ jsx(
              Input,
              {
                value,
                onChange: (event) => onLabelChange(itemKey, event.target.value),
                placeholder,
                disabled: saving
              }
            ) }),
            isModified ? /* @__PURE__ */ jsx(
              IconButton,
              {
                type: "button",
                variant: "ghost",
                size: "sm",
                onClick: () => onLabelChange(itemKey, ""),
                disabled: saving,
                "aria-label": t("appShell.sidebarCustomizationResetField", "Reset to default"),
                title: t("appShell.sidebarCustomizationResetField", "Reset to default"),
                children: /* @__PURE__ */ jsx(RotateCcw, { className: "size-3.5" })
              }
            ) : null
          ] }),
          isModified ? /* @__PURE__ */ jsxs("p", { className: "text-xs text-muted-foreground", children: [
            t("appShell.sidebarCustomizationDefault", "Default:"),
            " ",
            /* @__PURE__ */ jsx("span", { className: "font-medium text-foreground/80", children: placeholder })
          ] }) : null
        ] }),
        /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-2 pt-1.5", children: [
          hidden ? /* @__PURE__ */ jsx("span", { className: "rounded-full border border-border bg-muted px-2 py-0.5 text-xs font-medium uppercase tracking-wide text-muted-foreground", children: t("appShell.sidebarCustomizationHiddenBadge", "Hidden") }) : null,
          /* @__PURE__ */ jsx(
            Switch,
            {
              checked: !hidden,
              onCheckedChange: (next) => onHiddenChange(itemKey, next !== true),
              disabled: saving || ancestorHidden,
              "aria-label": t("appShell.sidebarCustomizationShowItem"),
              title: ancestorHidden ? t("appShell.sidebarCustomizationParentHiddenHint", "Parent is hidden \u2014 show parent first.") : void 0
            }
          )
        ] })
      ]
    }
  );
}
function SortableItemRow({ id, ...rowProps }) {
  const t = useT();
  const { attributes, listeners, setNodeRef, transform, transition, isDragging, setActivatorNodeRef } = useSortable({ id });
  const style = {
    transform: CSS.Transform.toString(transform),
    transition,
    opacity: isDragging ? 0.5 : 1
  };
  const dragHandle = /* @__PURE__ */ jsx(
    IconButton,
    {
      ref: setActivatorNodeRef,
      type: "button",
      variant: "ghost",
      size: "sm",
      className: "shrink-0 mt-1.5 cursor-grab touch-none active:cursor-grabbing",
      "aria-label": t("appShell.sidebarCustomizationDragToReorder", "Drag to reorder"),
      disabled: rowProps.saving,
      ...attributes,
      ...listeners,
      children: /* @__PURE__ */ jsx(GripVertical, { className: "size-4" })
    }
  );
  return /* @__PURE__ */ jsx("div", { ref: setNodeRef, style, children: /* @__PURE__ */ jsx(ItemRow, { ...rowProps, dragHandle }) });
}
function ItemRows({
  items,
  draft,
  saving,
  onLabelChange,
  onHiddenChange,
  t,
  depth = 0,
  groupKey,
  sensors,
  onDragEnd,
  ancestorHidden = false
}) {
  if (items.length === 0) return null;
  const renderRecursiveChildren = (item, parentHidden) => item.children && item.children.length > 0 ? /* @__PURE__ */ jsx(
    ItemRows,
    {
      items: item.children,
      draft,
      saving,
      onLabelChange,
      onHiddenChange,
      t,
      depth: depth + 1,
      ancestorHidden: parentHidden
    }
  ) : null;
  if (depth === 0 && groupKey && sensors && onDragEnd) {
    const ordered = applyItemOrder(items, resolveItemKey, draft.itemOrder?.[groupKey]);
    const ids = ordered.map((item) => resolveItemKey(item));
    return /* @__PURE__ */ jsx(DndContext, { sensors, collisionDetection: closestCenter, onDragEnd, children: /* @__PURE__ */ jsx(SortableContext, { items: ids, strategy: verticalListSortingStrategy, children: ordered.map((item) => {
      const itemKey = resolveItemKey(item);
      const ownHidden = draft.hiddenItemIds[itemKey] === true;
      return /* @__PURE__ */ jsxs(React.Fragment, { children: [
        /* @__PURE__ */ jsx(
          SortableItemRow,
          {
            id: itemKey,
            item,
            draft,
            saving,
            onLabelChange,
            onHiddenChange,
            t,
            depth,
            ancestorHidden
          }
        ),
        renderRecursiveChildren(item, ancestorHidden || ownHidden)
      ] }, itemKey);
    }) }) });
  }
  return /* @__PURE__ */ jsx(Fragment, { children: items.map((item) => {
    const itemKey = resolveItemKey(item);
    const ownHidden = draft.hiddenItemIds[itemKey] === true;
    return /* @__PURE__ */ jsxs(React.Fragment, { children: [
      /* @__PURE__ */ jsx(
        ItemRow,
        {
          item,
          draft,
          saving,
          onLabelChange,
          onHiddenChange,
          t,
          depth,
          ancestorHidden
        }
      ),
      renderRecursiveChildren(item, ancestorHidden || ownHidden)
    ] }, itemKey);
  }) });
}
function SidebarPreviewIcon({ item }) {
  if (item.icon) return /* @__PURE__ */ jsx(Fragment, { children: item.icon });
  if (item.iconName) {
    const resolved = resolveInjectedIcon(item.iconName);
    if (resolved) return /* @__PURE__ */ jsx(Fragment, { children: resolved });
  }
  if (item.iconMarkup) {
    return /* @__PURE__ */ jsx("span", { "aria-hidden": "true", dangerouslySetInnerHTML: { __html: item.iconMarkup } });
  }
  return /* @__PURE__ */ jsx("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" }) });
}
function SidebarPreview({
  groups,
  productName,
  pickFirstActive
}) {
  const t = useT();
  const activeKey = React.useMemo(() => {
    if (!pickFirstActive) return null;
    for (const group of groups) {
      for (const item of group.items) {
        if (item.hidden === true) continue;
        return resolveItemKey(item);
      }
    }
    return null;
  }, [groups, pickFirstActive]);
  return /* @__PURE__ */ jsx("div", { className: "relative w-[240px] overflow-hidden rounded-xl border bg-background shadow-sm", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 px-3 py-4", children: [
    /* @__PURE__ */ jsx("div", { className: "mb-2", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 rounded-xl p-3", children: [
      /* @__PURE__ */ jsx(
        Image,
        {
          src: "/open-mercato.svg",
          alt: productName,
          width: 40,
          height: 40,
          className: "rounded-full shrink-0"
        }
      ),
      /* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-foreground truncate", children: productName })
    ] }) }),
    /* @__PURE__ */ jsxs("div", { className: "mb-2 flex items-center gap-2 rounded-lg border border-border bg-background pl-2.5 pr-2 py-2 shadow-sm", children: [
      /* @__PURE__ */ jsx(Search, { className: "size-4 shrink-0 text-muted-foreground", "aria-hidden": true }),
      /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 text-sm text-muted-foreground/70 truncate", children: t("appShell.sidebarCustomizationPreviewSearchPlaceholder", "Search...") })
    ] }),
    groups.length === 0 ? /* @__PURE__ */ jsx("p", { className: "px-2 text-sm text-muted-foreground", children: t("appShell.sidebarCustomizationPreviewEmpty", "No groups to preview.") }) : /* @__PURE__ */ jsx("nav", { className: "flex flex-col gap-2", children: groups.map((group, gi) => {
      const visibleItems = group.items.filter((item) => item.hidden !== true);
      if (visibleItems.length === 0) return null;
      return /* @__PURE__ */ jsxs("div", { children: [
        /* @__PURE__ */ jsx("div", { className: "w-full px-1 justify-between flex text-xs font-medium uppercase tracking-wider text-muted-foreground/70 py-1", children: /* @__PURE__ */ jsx("span", { children: group.name }) }),
        /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-1", children: visibleItems.map((item) => {
          const itemKey = resolveItemKey(item);
          const isActive = activeKey === itemKey;
          return /* @__PURE__ */ jsxs(
            "div",
            {
              className: `relative text-sm font-medium rounded-lg inline-flex items-center w-full px-3 py-2 gap-2 ${isActive ? "bg-muted text-foreground" : "text-muted-foreground"}`,
              children: [
                isActive ? /* @__PURE__ */ jsx(
                  "span",
                  {
                    "aria-hidden": true,
                    className: "absolute left-[-12px] top-2 w-1 h-5 rounded-r bg-foreground"
                  }
                ) : null,
                /* @__PURE__ */ jsx("span", { className: "flex items-center justify-center shrink-0", children: /* @__PURE__ */ jsx(SidebarPreviewIcon, { item }) }),
                /* @__PURE__ */ jsx("span", { className: "truncate", children: item.title })
              ]
            },
            itemKey
          );
        }) }),
        gi < groups.length - 1 ? /* @__PURE__ */ jsx("div", { className: "my-2 border-t -ml-3 -mr-4" }) : null
      ] }, resolveGroupKey(group));
    }) })
  ] }) });
}
var SidebarCustomizationEditor_default = SidebarCustomizationEditor;
export {
  SidebarCustomizationEditor,
  SidebarCustomizationEditor_default as default
};
//# sourceMappingURL=SidebarCustomizationEditor.js.map
