"use client";
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
import * as React from "react";
import { Popover, PopoverAnchor, PopoverContent } from "../../primitives/popover.js";
import { VisuallyHidden } from "@radix-ui/react-visually-hidden";
import { Alert, AlertDescription } from "../../primitives/alert.js";
import { Button } from "../../primitives/button.js";
import { Input } from "../../primitives/input.js";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle
} from "../../primitives/dialog.js";
import { Filter, Save, Trash2 } from "lucide-react";
import { useT } from "@open-mercato/shared/lib/i18n/context";
import {
  deserializeTreeFromPersist,
  isPersistedFilterTree,
  serializeTreeForPersist
} from "@open-mercato/shared/lib/query/advanced-filter-tree";
import { getDefaultOperator } from "@open-mercato/shared/lib/query/advanced-filter";
import { AdvancedFilterBuilder } from "./AdvancedFilterBuilder.js";
import { FilterEmptyState } from "./FilterEmptyState.js";
import { QuickFilters } from "./QuickFilters.js";
import { FilterFieldPicker } from "./FilterFieldPicker.js";
import { treeReducer } from "./treeReducer.js";
import { flash } from "../FlashMessages.js";
const SAVED_FILTER_STORAGE_PREFIX = "open-mercato:advanced-filters:";
const MAX_SAVED_FILTERS = 20;
const CURRENT_SAVED_FILTERS_VERSION = 1;
function makeSavedFilterStorageKey(key) {
  const trimmed = key?.trim();
  return trimmed ? `${SAVED_FILTER_STORAGE_PREFIX}${trimmed}` : null;
}
function isSavedAdvancedFilter(value) {
  if (!value || typeof value !== "object") return false;
  const record = value;
  return typeof record.id === "string" && typeof record.name === "string" && typeof record.createdAt === "string" && typeof record.updatedAt === "string" && isPersistedFilterTree(record.tree);
}
function readSavedFilters(storageKey) {
  if (typeof window === "undefined") return [];
  try {
    const raw = window.localStorage.getItem(storageKey);
    if (!raw) return [];
    const parsed = JSON.parse(raw);
    if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
      const envelope = parsed;
      if (envelope.v === 1 && Array.isArray(envelope.filters)) {
        return envelope.filters.filter(isSavedAdvancedFilter);
      }
    }
    if (Array.isArray(parsed)) {
      return parsed.filter(isSavedAdvancedFilter);
    }
    return [];
  } catch {
    return [];
  }
}
function writeSavedFilters(storageKey, filters) {
  if (typeof window === "undefined") return;
  const envelope = { v: CURRENT_SAVED_FILTERS_VERSION, filters };
  window.localStorage.setItem(storageKey, JSON.stringify(envelope));
}
function SaveFilterDialog({
  open,
  onOpenChange,
  onSave,
  t
}) {
  const [name, setName] = React.useState("");
  const [saving, setSaving] = React.useState(false);
  const [error, setError] = React.useState(null);
  const trimmed = name.trim();
  React.useEffect(() => {
    if (!open) {
      setName("");
      setSaving(false);
      setError(null);
    }
  }, [open]);
  const submit = React.useCallback(async () => {
    if (!trimmed || saving) return;
    setSaving(true);
    setError(null);
    try {
      await onSave(trimmed);
      onOpenChange(false);
    } catch (err) {
      setError(err instanceof Error ? err.message : t("ui.advancedFilter.saveFilter.error", "Failed to save filter"));
    } finally {
      setSaving(false);
    }
  }, [onSave, onOpenChange, saving, t, trimmed]);
  return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsx(DialogContent, { elevated: true, className: "sm:max-w-md", "data-advanced-filter-portal": true, children: /* @__PURE__ */ jsxs(
    "form",
    {
      className: "contents",
      onSubmit: (event) => {
        event.preventDefault();
        void submit();
      },
      children: [
        /* @__PURE__ */ jsxs(DialogHeader, { children: [
          /* @__PURE__ */ jsx(DialogTitle, { children: t("ui.advancedFilter.saveFilter.title", "Save filter") }),
          /* @__PURE__ */ jsx(DialogDescription, { children: t("ui.advancedFilter.saveFilter.description", "Name this filter so you can reuse the current conditions later.") })
        ] }),
        /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
          /* @__PURE__ */ jsx(
            Input,
            {
              value: name,
              onChange: (event) => setName(event.target.value),
              placeholder: t("ui.advancedFilter.saveFilter.placeholder", "Filter name"),
              "aria-label": t("ui.advancedFilter.saveFilter.nameAriaLabel", "Filter name"),
              autoFocus: true
            }
          ),
          error ? /* @__PURE__ */ jsx("p", { className: "text-sm text-status-error-text", children: error }) : null
        ] }),
        /* @__PURE__ */ jsxs(DialogFooter, { children: [
          /* @__PURE__ */ jsx(Button, { type: "button", variant: "outline", onClick: () => onOpenChange(false), children: t("common.cancel", "Cancel") }),
          /* @__PURE__ */ jsx(Button, { type: "submit", disabled: !trimmed || saving, children: saving ? t("ui.advancedFilter.saveFilter.saving", "Saving...") : t("ui.advancedFilter.saveFilter.submit", "Save filter") })
        ] })
      ]
    }
  ) }) });
}
function SavedFiltersSection({
  filters,
  canSaveCurrent,
  onSaveClick,
  onApply,
  onDelete,
  t
}) {
  if (!canSaveCurrent && filters.length === 0) return null;
  return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", "data-testid": "advanced-filter-saved-filters", children: [
    /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3", children: [
      /* @__PURE__ */ jsx("div", { className: "text-overline font-medium uppercase tracking-widest text-muted-foreground", children: t("ui.advancedFilter.savedFilters.heading", "Saved filters") }),
      canSaveCurrent ? /* @__PURE__ */ jsxs(
        Button,
        {
          "data-testid": "advanced-filter-save-trigger",
          type: "button",
          variant: "outline",
          size: "sm",
          className: "h-8 rounded-full gap-1.5",
          onClick: onSaveClick,
          children: [
            /* @__PURE__ */ jsx(Save, { className: "size-3.5 text-muted-foreground" }),
            t("ui.advancedFilter.saveFilter.button", "Save filter")
          ]
        }
      ) : null
    ] }),
    filters.length ? /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-2", children: filters.map((filter) => /* @__PURE__ */ jsxs("div", { className: "inline-flex max-w-full items-center overflow-hidden rounded-full border border-border bg-background", children: [
      /* @__PURE__ */ jsxs(
        Button,
        {
          type: "button",
          variant: "ghost",
          size: "sm",
          className: "h-8 min-w-0 rounded-r-none px-3 gap-1.5",
          title: filter.name,
          onClick: () => onApply(filter),
          children: [
            /* @__PURE__ */ jsx(Filter, { className: "size-3.5 shrink-0 text-muted-foreground" }),
            /* @__PURE__ */ jsx("span", { className: "truncate", children: filter.name })
          ]
        }
      ),
      /* @__PURE__ */ jsx(
        Button,
        {
          type: "button",
          variant: "ghost",
          size: "sm",
          className: "h-8 w-8 rounded-l-none px-0 text-muted-foreground hover:text-status-error-text",
          "aria-label": `${t("ui.advancedFilter.savedFilters.delete", "Delete saved filter")}: ${filter.name}`,
          onClick: () => onDelete(filter.id),
          children: /* @__PURE__ */ jsx(Trash2, { className: "size-3.5" })
        }
      )
    ] }, filter.id)) }) : /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: t("ui.advancedFilter.savedFilters.empty", "No saved filters yet") })
  ] });
}
function AdvancedFilterPanel(props) {
  const t = useT();
  const empty = props.value.root.children.length === 0;
  const [pickerOpen, setPickerOpen] = React.useState(false);
  const [saveDialogOpen, setSaveDialogOpen] = React.useState(false);
  const [savedFilters, setSavedFilters] = React.useState([]);
  const addConditionRef = React.useRef(null);
  const savedFilterStorageKey = React.useMemo(
    () => makeSavedFilterStorageKey(props.savedFilterStorageKey),
    [props.savedFilterStorageKey]
  );
  const wasOpenRef = React.useRef(props.open);
  React.useEffect(() => {
    if (wasOpenRef.current && !props.open && props.onFlush) props.onFlush();
    wasOpenRef.current = props.open;
  }, [props.open, props.onFlush]);
  const handlePresetApply = (tree) => {
    props.onChange(tree);
    props.onOpenChange(false);
  };
  React.useEffect(() => {
    if (!savedFilterStorageKey) {
      setSavedFilters([]);
      return;
    }
    if (props.open) {
      setSavedFilters(readSavedFilters(savedFilterStorageKey));
    }
  }, [props.open, savedFilterStorageKey]);
  const persistSavedFilters = React.useCallback((next) => {
    if (!savedFilterStorageKey) return;
    setSavedFilters(next);
    writeSavedFilters(savedFilterStorageKey, next);
  }, [savedFilterStorageKey]);
  const handleSaveFilter = React.useCallback(async (name) => {
    if (!savedFilterStorageKey) return;
    const now = (/* @__PURE__ */ new Date()).toISOString();
    const normalizedName = name.trim();
    const existing = savedFilters.find((item) => item.name.trim().toLowerCase() === normalizedName.toLowerCase());
    const record = {
      id: existing?.id ?? crypto.randomUUID(),
      name: normalizedName,
      tree: serializeTreeForPersist(props.value),
      createdAt: existing?.createdAt ?? now,
      updatedAt: now
    };
    const next = [
      record,
      ...savedFilters.filter((item) => item.id !== record.id)
    ].slice(0, MAX_SAVED_FILTERS);
    persistSavedFilters(next);
    flash(t("ui.advancedFilter.saveFilter.success", "Filter saved"), "success");
  }, [persistSavedFilters, props.value, savedFilterStorageKey, savedFilters, t]);
  const handleApplySavedFilter = React.useCallback((filter) => {
    const tree = deserializeTreeFromPersist(filter.tree);
    if (!tree) return;
    props.onChange(tree);
    props.onOpenChange(false);
  }, [props.onChange, props.onOpenChange]);
  const handleDeleteSavedFilter = React.useCallback((filterId) => {
    persistSavedFilters(savedFilters.filter((item) => item.id !== filterId));
  }, [persistSavedFilters, savedFilters]);
  const shouldShowSavedFilters = Boolean(savedFilterStorageKey && (!empty || savedFilters.length > 0));
  const savedFiltersSection = shouldShowSavedFilters ? /* @__PURE__ */ jsx(
    SavedFiltersSection,
    {
      filters: savedFilters,
      canSaveCurrent: !empty,
      onSaveClick: () => setSaveDialogOpen(true),
      onApply: handleApplySavedFilter,
      onDelete: handleDeleteSavedFilter,
      t
    }
  ) : null;
  const emptyStateShortcuts = props.presets.length || savedFiltersSection ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4", children: [
    props.presets.length ? /* @__PURE__ */ jsx(QuickFilters, { presets: props.presets, userId: props.userId, onApply: handlePresetApply }) : null,
    savedFiltersSection
  ] }) : null;
  const builderErrors = React.useMemo(
    () => props.pendingErrors.map((e) => ({ ruleId: e.ruleId, messageKey: e.messageKey, message: e.message })),
    [props.pendingErrors]
  );
  const ignoreAdvancedFilterPortalInteractions = React.useCallback((event) => {
    const target = event.target;
    if (!(target instanceof Element)) return;
    if (target.closest("[data-advanced-filter-portal]")) {
      event.preventDefault();
    }
  }, []);
  return /* @__PURE__ */ jsxs(Popover, { open: props.open, onOpenChange: props.onOpenChange, children: [
    props.triggerRef ? /* @__PURE__ */ jsx(PopoverAnchor, { virtualRef: props.triggerRef }) : null,
    /* @__PURE__ */ jsxs(
      PopoverContent,
      {
        className: "w-[min(calc(100vw-2rem),780px)] max-h-[min(calc(100vh-6rem),720px)] overflow-y-auto p-0 gap-0",
        align: "end",
        sideOffset: 8,
        "data-testid": "advanced-filter-panel",
        onPointerDownOutside: ignoreAdvancedFilterPortalInteractions,
        onFocusOutside: ignoreAdvancedFilterPortalInteractions,
        onInteractOutside: ignoreAdvancedFilterPortalInteractions,
        children: [
          /* @__PURE__ */ jsx(VisuallyHidden, { children: /* @__PURE__ */ jsx("h2", { children: t("ui.advancedFilter.dialog.title", "Advanced filter") }) }),
          /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
            empty ? /* @__PURE__ */ jsx(
              FilterEmptyState,
              {
                onAddCondition: () => setPickerOpen(true),
                addConditionRef,
                aiSlot: props.aiSlot,
                quickFilters: emptyStateShortcuts
              }
            ) : /* @__PURE__ */ jsxs(Fragment, { children: [
              /* @__PURE__ */ jsx(
                AdvancedFilterBuilder,
                {
                  fields: props.fields,
                  value: props.value,
                  onChange: props.onChange,
                  onApply: props.onApply,
                  onClear: props.onClear,
                  pendingErrors: builderErrors
                }
              ),
              savedFiltersSection ? /* @__PURE__ */ jsx("div", { className: "border-t border-border p-3", children: savedFiltersSection }) : null
            ] }),
            props.pendingErrors.length > 0 ? /* @__PURE__ */ jsx("div", { className: "p-3 border-t border-border", "data-testid": "filter-validation-banner", children: /* @__PURE__ */ jsx(Alert, { variant: "destructive", children: /* @__PURE__ */ jsx(AlertDescription, { children: props.pendingErrors.length === 1 ? t("ui.advancedFilter.banner.incomplete", "{count} filter is incomplete \u2014 filters won't apply until all values are picked.", { count: 1 }) : t("ui.advancedFilter.banner.incompletePlural", "{count} filters are incomplete \u2014 filters won't apply until all values are picked.", { count: props.pendingErrors.length }) }) }) }) : null
          ] })
        ]
      }
    ),
    /* @__PURE__ */ jsx(
      FilterFieldPicker,
      {
        fields: props.fields,
        open: pickerOpen,
        onOpenChange: setPickerOpen,
        onSelect: (field) => {
          const next = treeReducer(props.value, {
            type: "addRule",
            groupId: props.value.root.id,
            defaultField: field.key,
            defaultOperator: getDefaultOperator(field.type)
          });
          props.onChange(next);
        },
        triggerRef: addConditionRef
      }
    ),
    /* @__PURE__ */ jsx(
      SaveFilterDialog,
      {
        open: saveDialogOpen,
        onOpenChange: setSaveDialogOpen,
        onSave: handleSaveFilter,
        t
      }
    )
  ] });
}
export {
  AdvancedFilterPanel
};
//# sourceMappingURL=AdvancedFilterPanel.js.map
