'use client';

import { XIcon } from '@phosphor-icons/react';
import * as React from 'react';

import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { cn } from '@lib/utils';

interface TagInputProps extends Omit<
  React.InputHTMLAttributes<HTMLInputElement>,
  'onChange' | 'value'
> {
  value?: string[];
  onChange?: (tags: string[]) => void;
  maxTags?: number;
  placeholder?: string;
  'aria-invalid'?: boolean;
  disabled?: boolean;
}

const TagInput = React.forwardRef<HTMLInputElement, TagInputProps>(
  (
    {
      value: tags = [],
      onChange,
      maxTags,
      placeholder = 'Add a tag',
      disabled,
      className,
      'aria-invalid': ariaInvalid,
      ...props
    },
    ref,
  ) => {
    const [inputValue, setInputValue] = React.useState('');
    const inputRef = React.useRef<HTMLInputElement>(null);

    const handleAddTag = () => {
      if (inputValue.trim() !== '' && !tags.includes(inputValue.trim())) {
        if (maxTags && tags.length >= maxTags) {
          // Optionally show a toast or message that max tags limit is reached
          return;
        }
        onChange?.([...tags, inputValue.trim()]);
        setInputValue('');
      }
    };

    const handleRemoveTag = (tagToRemove: string) => {
      onChange?.(tags.filter((tag) => tag !== tagToRemove));
    };

    const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
      setInputValue(e.target.value);
    };

    const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
      if (e.key === 'Enter') {
        e.preventDefault();
        handleAddTag();
      } else if (
        e.key === 'Backspace' &&
        inputValue === '' &&
        tags.length > 0
      ) {
        e.preventDefault();
        handleRemoveTag(tags[tags.length - 1]);
      }
    };

    return (
      <div
        aria-invalid={ariaInvalid}
        className={cn(
          'flex flex-wrap items-center gap-2 rounded-md border border-input bg-input/20 p-1 text-xs transition-colors focus-within:ring-ring/30 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:bg-input/30',
          disabled && 'cursor-not-allowed opacity-50',
          className,
        )}
      >
        {tags.map((tag) => (
          <Badge
            key={tag}
            variant="outline"
            className="flex items-center gap-1 bg-primary text-white"
          >
            {tag}
            {!disabled && (
              <Button
                type="button"
                variant="ghost"
                size="icon-xs"
                className="size-4 rounded-full"
                onClick={() => handleRemoveTag(tag)}
                disabled={disabled}
              >
                <XIcon className="size-3" />
                <span className="sr-only">Remove tag</span>
              </Button>
            )}
          </Badge>
        ))}
        <Input
          ref={ref || inputRef}
          type="text"
          value={inputValue}
          onChange={handleInputChange}
          onKeyDown={handleKeyDown}
          placeholder={
            maxTags && tags.length >= maxTags ? 'Max tags reached' : placeholder
          }
          className="flex-1 border-none bg-transparent shadow-none focus-visible:ring-0 px-1 h-6 min-w-20"
          disabled={disabled || !!(maxTags && tags.length >= maxTags)}
          {...props}
        />
      </div>
    );
  },
);
TagInput.displayName = 'TagInput';

export { TagInput };
