"use client";
import { jsx, jsxs } from "react/jsx-runtime";
import * as React from "react";
import { useT } from "@open-mercato/shared/lib/i18n/context";
import { Button } from "../../primitives/button.js";
import { Tag } from "../../primitives/tag.js";
function normalizeOptions(input) {
  if (!Array.isArray(input)) return [];
  return input.map((option) => {
    if (typeof option === "string") {
      const trimmed = option.trim();
      if (!trimmed) return null;
      return { value: trimmed, label: trimmed };
    }
    const value = typeof option.value === "string" ? option.value.trim() : "";
    if (!value) return null;
    return {
      value,
      label: option.label?.trim() || value,
      description: option.description ?? null
    };
  }).filter((option) => !!option);
}
function TagsInput({
  value,
  onChange,
  placeholder,
  suggestions,
  loadSuggestions,
  selectedOptions,
  resolveLabel,
  resolveDescription,
  autoFocus,
  disabled = false,
  allowCustomValues = true,
  showSuggestionsOnFocus = true,
  suppressInitialSuggestionsOnFocus = false
}) {
  const t = useT();
  const [input, setInput] = React.useState("");
  const [asyncOptions, setAsyncOptions] = React.useState([]);
  const [loading, setLoading] = React.useState(false);
  const [touched, setTouched] = React.useState(false);
  const suppressBlurCommitRef = React.useRef(false);
  const suppressSuggestionsOnFocusRef = React.useRef(Boolean(autoFocus && suppressInitialSuggestionsOnFocus && !disabled));
  const valueRef = React.useRef(value);
  React.useEffect(() => {
    valueRef.current = value;
  }, [value]);
  React.useEffect(() => {
    suppressSuggestionsOnFocusRef.current = Boolean(autoFocus && suppressInitialSuggestionsOnFocus && !disabled);
  }, [autoFocus, disabled, suppressInitialSuggestionsOnFocus]);
  const staticOptions = React.useMemo(() => normalizeOptions(suggestions), [suggestions]);
  const selectedOptionList = React.useMemo(
    () => normalizeOptions(selectedOptions),
    [selectedOptions]
  );
  const optionMap = React.useMemo(() => {
    const map = /* @__PURE__ */ new Map();
    const register = (option) => {
      if (!map.has(option.value)) {
        map.set(option.value, option);
      }
    };
    staticOptions.forEach(register);
    asyncOptions.forEach(register);
    selectedOptionList.forEach(register);
    value.forEach((val) => {
      if (map.has(val)) return;
      map.set(val, {
        value: val,
        label: resolveLabel?.(val) ?? val,
        description: resolveDescription?.(val) ?? null
      });
    });
    return map;
  }, [asyncOptions, resolveDescription, resolveLabel, selectedOptionList, staticOptions, value]);
  const availableOptions = React.useMemo(() => {
    return Array.from(optionMap.values()).filter((option) => !value.includes(option.value));
  }, [optionMap, value]);
  const filteredSuggestions = React.useMemo(() => {
    const query = input.toLowerCase().trim();
    if (!query) return availableOptions.slice(0, 8);
    return availableOptions.filter((option) => {
      const labelMatch = option.label.toLowerCase().includes(query);
      const descMatch = option.description?.toLowerCase().includes(query);
      return labelMatch || Boolean(descMatch);
    });
  }, [availableOptions, input]);
  React.useEffect(() => {
    if (!loadSuggestions || !touched || disabled) return;
    const query = input.trim();
    let cancelled = false;
    const handle = window.setTimeout(async () => {
      setLoading(true);
      try {
        const items = await loadSuggestions(query);
        if (!cancelled) {
          setAsyncOptions(normalizeOptions(items));
        }
      } finally {
        if (!cancelled) setLoading(false);
      }
    }, 200);
    return () => {
      cancelled = true;
      window.clearTimeout(handle);
    };
  }, [disabled, input, loadSuggestions, touched]);
  const addValue = React.useCallback(
    (nextValue) => {
      if (disabled) return;
      const trimmed = nextValue.trim();
      if (!trimmed) return;
      const currentValue = valueRef.current;
      if (currentValue.includes(trimmed)) return;
      const next = [...currentValue, trimmed];
      valueRef.current = next;
      onChange(next);
    },
    [disabled, onChange]
  );
  const findOptionForInput = React.useCallback(
    (raw) => {
      const query = raw.trim().toLowerCase();
      if (!query) return null;
      for (const option of optionMap.values()) {
        if (option.value === raw.trim()) return option;
        if (option.label.toLowerCase() === query) return option;
      }
      return null;
    },
    [optionMap]
  );
  const addTag = React.useCallback(
    (raw) => {
      if (disabled) return;
      const option = findOptionForInput(raw);
      if (option) {
        addValue(option.value);
        return;
      }
      if (!allowCustomValues) return;
      addValue(raw);
    },
    [addValue, allowCustomValues, disabled, findOptionForInput]
  );
  const removeTag = React.useCallback(
    (tag) => {
      if (disabled) return;
      const next = valueRef.current.filter((candidate) => candidate !== tag);
      valueRef.current = next;
      onChange(next);
    },
    [disabled, onChange]
  );
  return /* @__PURE__ */ jsx(
    "div",
    {
      className: [
        "w-full rounded border px-2 py-1",
        disabled ? "bg-muted text-muted-foreground/80 cursor-not-allowed" : ""
      ].filter(Boolean).join(" "),
      "aria-disabled": disabled || void 0,
      children: /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-1", children: [
        value.map((tag) => {
          const option = optionMap.get(tag);
          const label = option?.label ?? tag;
          const description = option?.description;
          return /* @__PURE__ */ jsx(
            Tag,
            {
              shape: "square",
              variant: "default",
              disabled,
              onRemove: () => removeTag(tag),
              removeAriaLabel: t("ui.inputs.tagsInput.removeTag", "Remove {label}", { label }),
              children: /* @__PURE__ */ jsxs("span", { className: "flex flex-col items-start leading-tight", children: [
                /* @__PURE__ */ jsx("span", { className: "whitespace-nowrap", children: label }),
                description ? /* @__PURE__ */ jsx("span", { className: "text-overline text-muted-foreground", children: description }) : null
              ] })
            },
            tag
          );
        }),
        /* @__PURE__ */ jsx(
          "input",
          {
            className: "flex-1 min-w-[80px] sm:min-w-[120px] border-0 py-1 text-sm outline-none disabled:bg-transparent",
            value: input,
            placeholder: placeholder || t("ui.inputs.tagsInput.placeholder", "Add tag and press Enter"),
            autoFocus,
            "data-crud-focus-target": "",
            disabled,
            onFocus: () => {
              if (suppressSuggestionsOnFocusRef.current) {
                suppressSuggestionsOnFocusRef.current = false;
                return;
              }
              if (showSuggestionsOnFocus) {
                setTouched(true);
              }
            },
            onMouseDown: () => {
              setTouched(true);
            },
            onChange: (event) => {
              setTouched(true);
              setInput(event.target.value);
            },
            onKeyDown: (event) => {
              if (disabled) return;
              if (event.key === "Enter" || event.key === ",") {
                event.preventDefault();
                addTag(input);
                setInput("");
              } else if (event.key === "Backspace" && input === "" && value.length > 0) {
                removeTag(value[value.length - 1]);
              }
            },
            onBlur: () => {
              if (disabled) return;
              if (suppressBlurCommitRef.current) {
                suppressBlurCommitRef.current = false;
                setInput("");
                return;
              }
              addTag(input);
              setInput("");
            }
          }
        ),
        loading && touched ? /* @__PURE__ */ jsx("div", { className: "basis-full mt-1 text-xs text-muted-foreground", children: "Loading suggestions\u2026" }) : null,
        !loading && filteredSuggestions.length ? /* @__PURE__ */ jsx("div", { className: "basis-full mt-1 flex flex-col gap-1", children: filteredSuggestions.map((option) => /* @__PURE__ */ jsxs(
          Button,
          {
            type: "button",
            variant: "ghost",
            size: "sm",
            className: "w-full justify-start font-normal flex flex-col items-start text-xs px-1.5 py-1",
            onMouseDown: (event) => {
              suppressBlurCommitRef.current = true;
              event.preventDefault();
            },
            onClick: () => {
              suppressBlurCommitRef.current = false;
              addValue(option.value);
              setInput("");
            },
            children: [
              /* @__PURE__ */ jsx("span", { children: option.label }),
              option.description ? /* @__PURE__ */ jsx("span", { className: "text-overline text-muted-foreground", children: option.description }) : null
            ]
          },
          option.value
        )) }) : null
      ] })
    }
  );
}
export {
  TagsInput
};
//# sourceMappingURL=TagsInput.js.map
