"use client";
import { jsx, jsxs } from "react/jsx-runtime";
import * as React from "react";
import Link from "next/link";
import { usePathname, useSearchParams } from "next/navigation";
import { Plus, Settings, Save } from "lucide-react";
import { Button } from "@open-mercato/ui/primitives/button";
import { Input } from "@open-mercato/ui/primitives/input";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
  DialogTrigger
} from "@open-mercato/ui/primitives/dialog";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue
} from "@open-mercato/ui/primitives/select";
import { Spinner } from "@open-mercato/ui/primitives/spinner";
import { flash } from "@open-mercato/ui/backend/FlashMessages";
import { buildHrefWithReturnTo } from "@open-mercato/shared/lib/navigation/returnTo";
import { renderDictionaryColor, renderDictionaryIcon } from "./dictionaryAppearance.js";
import { AppearanceSelector, useAppearanceState } from "./AppearanceSelector.js";
import { createLogger } from "@open-mercato/shared/lib/logger";
const logger = createLogger("dictionaries").child({ component: "DictionaryEntrySelect" });
const DEFAULT_APPEARANCE_LABELS = {
  colorLabel: "Color",
  colorHelp: "Pick a highlight color for this entry.",
  colorClearLabel: "Remove color",
  iconLabel: "Icon or emoji",
  iconPlaceholder: "Type an emoji or icon token.",
  iconPickerTriggerLabel: "Browse icons and emoji",
  iconSearchPlaceholder: "Search icons or emojis\u2026",
  iconSearchEmptyLabel: "No icons match your search.",
  iconSuggestionsLabel: "Suggestions",
  iconClearLabel: "Remove icon",
  previewEmptyLabel: "No appearance selected"
};
function DictionaryEntrySelect({
  id,
  value,
  onChange,
  fetchOptions,
  createOption,
  labels,
  manageHref,
  selectClassName,
  seedOptions,
  allowInlineCreate = true,
  allowAppearance = false,
  appearanceLabels,
  disabled: disabledProp = false,
  showLabelInput = true,
  showManage = true,
  sortOptions = "label_asc",
  showActiveAppearance = true
}) {
  const pathname = usePathname();
  const searchParams = useSearchParams();
  const [options, setOptions] = React.useState([]);
  const [loading, setLoading] = React.useState(true);
  const [saving, setSaving] = React.useState(false);
  const [dialogOpen, setDialogOpen] = React.useState(false);
  const [newValue, setNewValue] = React.useState("");
  const [newLabel, setNewLabel] = React.useState("");
  const [formError, setFormError] = React.useState(null);
  const appearance = useAppearanceState(null, null);
  const loadOptions = React.useCallback(async () => {
    setLoading(true);
    try {
      const items = await fetchOptions();
      setOptions(sortOptions === "none" ? items : items.slice().sort((a, b) => a.label.localeCompare(b.label, void 0, { sensitivity: "base" })));
    } catch (err) {
      logger.error("Failed to fetch options", { err });
      flash(labels.errorLoad, "error");
      setOptions([]);
    } finally {
      setLoading(false);
    }
  }, [fetchOptions, labels.errorLoad, sortOptions]);
  React.useEffect(() => {
    loadOptions().catch(() => {
    });
  }, [loadOptions]);
  const resetDialogState = React.useCallback(() => {
    setNewValue("");
    setNewLabel("");
    setFormError(null);
    appearance.setColor(null);
    appearance.setIcon(null);
    setSaving(false);
  }, [appearance]);
  React.useEffect(() => {
    if (!dialogOpen) resetDialogState();
  }, [dialogOpen, resetDialogState]);
  const mergedOptions = React.useMemo(() => {
    if (!Array.isArray(seedOptions) || !seedOptions.length) return options;
    const merged = [];
    const seen = /* @__PURE__ */ new Set();
    for (const option of seedOptions) {
      if (!option.value || seen.has(option.value)) continue;
      seen.add(option.value);
      merged.push(option);
    }
    for (const option of options) {
      if (seen.has(option.value)) continue;
      seen.add(option.value);
      merged.push(option);
    }
    return merged;
  }, [options, seedOptions]);
  const activeOption = React.useMemo(
    () => mergedOptions.find((option) => option.value === value) ?? null,
    [mergedOptions, value]
  );
  const displayOptions = React.useMemo(() => {
    if (!value || activeOption) return mergedOptions;
    return [
      {
        value,
        label: value,
        color: null,
        icon: null
      },
      ...mergedOptions
    ];
  }, [activeOption, mergedOptions, value]);
  const handleCreate = React.useCallback(async () => {
    if (!createOption) return;
    const trimmedValue = newValue.trim();
    if (!trimmedValue.length) {
      setFormError(labels.emptyError);
      return;
    }
    setSaving(true);
    try {
      const payload = await createOption({
        value: trimmedValue,
        label: showLabelInput ? newLabel.trim() || void 0 : void 0,
        color: allowAppearance && appearance.color ? appearance.color : void 0,
        icon: allowAppearance && appearance.icon ? appearance.icon : void 0
      });
      if (!payload) throw new Error("createOption did not return an entry");
      setOptions((previous) => {
        const map = new Map(previous.map((option) => [option.value, option]));
        map.set(payload.value, {
          value: payload.value,
          label: payload.label,
          color: payload.color ?? null,
          icon: payload.icon ?? null
        });
        const nextOptions = Array.from(map.values());
        return sortOptions === "none" ? nextOptions : nextOptions.sort((a, b) => a.label.localeCompare(b.label, void 0, { sensitivity: "base" }));
      });
      await loadOptions();
      onChange(payload.value);
      setDialogOpen(false);
      if (labels.successCreateLabel) {
        flash(labels.successCreateLabel, "success");
      }
    } catch (err) {
      logger.error("Failed to create option", { err });
      flash(labels.errorSave, "error");
    } finally {
      setSaving(false);
    }
  }, [
    allowAppearance,
    appearance.color,
    appearance.icon,
    createOption,
    labels.emptyError,
    labels.errorSave,
    labels.successCreateLabel,
    loadOptions,
    newLabel,
    newValue,
    onChange,
    sortOptions
  ]);
  const handleDialogKeyDown = React.useCallback(
    (event) => {
      if (event.key === "Escape") {
        event.preventDefault();
        if (!saving) {
          setDialogOpen(false);
        }
        return;
      }
      if (event.key === "Enter" && (event.metaKey || event.ctrlKey)) {
        event.preventDefault();
        if (!saving && newValue.trim().length) {
          handleCreate().catch(() => {
          });
        } else if (!saving && !newValue.trim().length) {
          setFormError(labels.emptyError);
        }
      }
    },
    [handleCreate, labels.emptyError, newValue, saving]
  );
  const shortcutHint = React.useMemo(() => {
    const provided = typeof labels.saveShortcutHint === "string" ? labels.saveShortcutHint.trim() : "";
    if (provided.length) return provided;
    return "\u2318/Ctrl + Enter";
  }, [labels.saveShortcutHint]);
  const disabled = disabledProp || loading || saving;
  const manageLink = manageHref ?? "/backend/config/dictionaries";
  const returnTo = React.useMemo(() => {
    const query = searchParams?.toString() ?? "";
    if (!pathname) return null;
    return query.length ? `${pathname}?${query}` : pathname;
  }, [pathname, searchParams]);
  const manageLinkWithReturnTo = React.useMemo(
    () => buildHrefWithReturnTo(manageLink, returnTo),
    [manageLink, returnTo]
  );
  const optionsKey = React.useMemo(
    () => displayOptions.map((option) => `${option.value}:${option.label}`).join("\0"),
    [displayOptions]
  );
  return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
    /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
      /* @__PURE__ */ jsxs(
        Select,
        {
          value: value ?? "",
          onValueChange: (next) => {
            if (!next) return;
            onChange(next);
          },
          disabled,
          children: [
            /* @__PURE__ */ jsx(
              SelectTrigger,
              {
                id,
                className: selectClassName,
                title: activeOption?.label ?? void 0,
                children: /* @__PURE__ */ jsx(SelectValue, { placeholder: labels.placeholder, children: activeOption?.label })
              }
            ),
            /* @__PURE__ */ jsx(SelectContent, { children: displayOptions.map((option) => /* @__PURE__ */ jsx(SelectItem, { value: option.value, children: option.label }, option.value)) })
          ]
        },
        `dictionary-entry:${value ?? ""}:${optionsKey}`
      ),
      /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
        allowInlineCreate && createOption ? /* @__PURE__ */ jsxs(Dialog, { open: dialogOpen, onOpenChange: setDialogOpen, children: [
          /* @__PURE__ */ jsx(DialogTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
            Button,
            {
              type: "button",
              variant: "outline",
              size: "icon",
              disabled,
              title: labels.addLabel,
              "aria-label": labels.addLabel,
              children: /* @__PURE__ */ jsx(Plus, { className: "h-4 w-4" })
            }
          ) }),
          /* @__PURE__ */ jsxs(DialogContent, { className: "sm:max-w-md", onKeyDown: handleDialogKeyDown, children: [
            /* @__PURE__ */ jsxs(DialogHeader, { children: [
              /* @__PURE__ */ jsx(DialogTitle, { children: labels.dialogTitle }),
              labels.addPrompt ? /* @__PURE__ */ jsx(DialogDescription, { children: labels.addPrompt }) : null
            ] }),
            /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
              /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
                /* @__PURE__ */ jsx("label", { className: "text-sm font-medium", children: labels.valueLabel }),
                /* @__PURE__ */ jsx(
                  Input,
                  {
                    type: "text",
                    value: newValue,
                    onChange: (event) => {
                      setNewValue(event.target.value);
                      if (formError) setFormError(null);
                    },
                    placeholder: labels.valuePlaceholder,
                    autoFocus: true,
                    disabled: saving
                  }
                )
              ] }),
              showLabelInput ? /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
                /* @__PURE__ */ jsx("label", { className: "text-sm font-medium", children: labels.labelLabel }),
                /* @__PURE__ */ jsx(
                  Input,
                  {
                    type: "text",
                    value: newLabel,
                    onChange: (event) => setNewLabel(event.target.value),
                    placeholder: labels.labelPlaceholder,
                    disabled: saving
                  }
                )
              ] }) : null,
              allowAppearance ? /* @__PURE__ */ jsx(
                AppearanceSelector,
                {
                  icon: appearance.icon,
                  color: appearance.color,
                  onIconChange: appearance.setIcon,
                  onColorChange: appearance.setColor,
                  labels: appearanceLabels ?? DEFAULT_APPEARANCE_LABELS
                }
              ) : null,
              formError ? /* @__PURE__ */ jsx("p", { className: "text-sm text-red-600", children: formError }) : null
            ] }),
            /* @__PURE__ */ jsxs(DialogFooter, { children: [
              /* @__PURE__ */ jsx(Button, { type: "button", variant: "outline", onClick: () => setDialogOpen(false), disabled: saving, children: labels.cancelLabel }),
              /* @__PURE__ */ jsxs(Button, { type: "button", onClick: handleCreate, disabled: saving || !newValue.trim(), children: [
                saving ? /* @__PURE__ */ jsx(Spinner, { className: "mr-2 h-4 w-4" }) : /* @__PURE__ */ jsx(Save, { className: "mr-2 h-4 w-4" }),
                /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-2", children: [
                  /* @__PURE__ */ jsx("span", { children: labels.saveLabel }),
                  !saving ? /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: `(${shortcutHint})` }) : null
                ] })
              ] })
            ] })
          ] })
        ] }) : null,
        showManage ? /* @__PURE__ */ jsx(Button, { asChild: true, variant: "ghost", size: "icon", title: labels.manageTitle, "aria-label": labels.manageTitle, children: /* @__PURE__ */ jsxs(Link, { href: manageLinkWithReturnTo, children: [
          /* @__PURE__ */ jsx(Settings, { className: "h-4 w-4" }),
          /* @__PURE__ */ jsx("span", { className: "sr-only", children: labels.manageTitle })
        ] }) }) : null
      ] })
    ] }),
    showActiveAppearance && activeOption && (activeOption.icon || activeOption.color) ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
      /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-2 rounded border border-dashed px-2 py-1", children: [
        activeOption.icon ? renderDictionaryIcon(activeOption.icon, "h-4 w-4") : null,
        activeOption.color ? renderDictionaryColor(activeOption.color, "h-4 w-4 rounded-sm") : null
      ] }),
      activeOption.color ? /* @__PURE__ */ jsx("span", { children: activeOption.color }) : null
    ] }) : null,
    loading ? /* @__PURE__ */ jsx("div", { className: "text-xs text-muted-foreground", children: labels.loadingLabel }) : null
  ] });
}
export {
  DictionaryEntrySelect
};
//# sourceMappingURL=DictionaryEntrySelect.js.map
