"use client";

import * as React from "react";
import { XIcon } from "lucide-react";

import { Badge } from "@/components/ui/badge";
import { Input } from "@/components/ui/input";
import { useTranslation } from "@/hooks/useTranslation";
import { cn } from "@/lib/utils";

interface TagInputProps extends Omit<
  React.ComponentProps<"input">,
  "value" | "onChange" | "type" | "defaultValue"
> {
  /** Current tags — order is preserved, duplicates are rejected on entry */
  value?: string[];
  onChange?: (value: string[]) => void;
  /** Extra classes for the outer wrapper */
  className?: string;
}

/**
 * Free-text list input (package features, tags, keywords).
 *
 * Commit a tag with Enter or a comma; Backspace on an empty field removes the
 * last one. Entries are trimmed and de-duplicated, so the array handed to the
 * API is always clean.
 *
 * Enter is intercepted rather than allowed to bubble — inside a `<form>` it
 * would otherwise submit the whole thing while the user is still adding items.
 */
function TagInput({
  value = [],
  onChange,
  className,
  disabled,
  ...props
}: TagInputProps) {
  const { t } = useTranslation();
  const [draft, setDraft] = React.useState("");

  function commit(raw: string) {
    const tag = raw.trim();
    if (!tag || value.includes(tag)) {
      setDraft("");
      return;
    }
    onChange?.([...value, tag]);
    setDraft("");
  }

  function removeAt(index: number) {
    onChange?.(value.filter((_, i) => i !== index));
  }

  function handleKeyDown(event: React.KeyboardEvent<HTMLInputElement>) {
    if (event.key === "Enter" || event.key === ",") {
      event.preventDefault();
      commit(draft);
      return;
    }
    if (event.key === "Backspace" && !draft && value.length > 0) {
      removeAt(value.length - 1);
    }
  }

  return (
    <div data-slot="tag-input" className={cn("flex flex-col gap-2", className)}>
      <Input
        {...props}
        disabled={disabled}
        value={draft}
        onChange={(event) => setDraft(event.target.value)}
        onKeyDown={handleKeyDown}
        // Committing on blur keeps a half-typed entry from being lost when the
        // user tabs straight to the submit button.
        onBlur={() => commit(draft)}
      />

      {value.length > 0 && (
        <div className="flex flex-wrap gap-1">
          {value.map((tag, index) => (
            <Badge key={tag} variant="secondary">
              {tag}
              <button
                type="button"
                disabled={disabled}
                aria-label={t("common.remove")}
                className="ms-1 rounded-full outline-none focus-visible:ring-3 focus-visible:ring-ring/50 disabled:pointer-events-none"
                onClick={() => removeAt(index)}
              >
                <XIcon />
              </button>
            </Badge>
          ))}
        </div>
      )}
    </div>
  );
}

export { TagInput };
