import { useState, useRef, useEffect, useCallback } from 'react'
import { X, Plus } from 'lucide-react'
import { tagsApi } from '@/api/tags'
import type { TagListItem } from '@/types'
import { cn } from '@/lib/utils'

interface TagInputProps {
  tags: string[]
  onChange: (tags: string[]) => void
  maxTags?: number
  placeholder?: string
  disabled?: boolean
}

export function TagInput({
  tags,
  onChange,
  maxTags = 10,
  placeholder = 'Add tags...',
  disabled = false,
}: TagInputProps) {
  const [inputValue, setInputValue] = useState('')
  const [suggestions, setSuggestions] = useState<TagListItem[]>([])
  const [showSuggestions, setShowSuggestions] = useState(false)
  const [selectedIndex, setSelectedIndex] = useState(-1)
  const inputRef = useRef<HTMLInputElement>(null)
  const wrapperRef = useRef<HTMLDivElement>(null)

  // Debounced search for suggestions
  useEffect(() => {
    const timer = setTimeout(() => {
      if (inputValue.length >= 1) {
        tagsApi
          .search(inputValue, 5)
          .then((results) => {
            // Filter out already selected tags
            const filtered = results.filter(
              (tag) => !tags.includes(tag.name)
            )
            setSuggestions(filtered)
            setShowSuggestions(filtered.length > 0)
            setSelectedIndex(-1)
          })
          .catch(console.error)
      } else {
        setSuggestions([])
        setShowSuggestions(false)
      }
    }, 200)

    return () => clearTimeout(timer)
  }, [inputValue, tags])

  // Close suggestions on outside click
  useEffect(() => {
    const handleClickOutside = (e: MouseEvent) => {
      if (wrapperRef.current && !wrapperRef.current.contains(e.target as Node)) {
        setShowSuggestions(false)
      }
    }
    document.addEventListener('mousedown', handleClickOutside)
    return () => document.removeEventListener('mousedown', handleClickOutside)
  }, [])

  const addTag = useCallback(
    (tagName: string) => {
      const normalized = tagName.trim()
      if (!normalized) return
      if (tags.length >= maxTags) return
      if (tags.includes(normalized)) return

      onChange([...tags, normalized])
      setInputValue('')
      setSuggestions([])
      setShowSuggestions(false)
      inputRef.current?.focus()
    },
    [tags, maxTags, onChange]
  )

  const removeTag = useCallback(
    (tagName: string) => {
      onChange(tags.filter((t) => t !== tagName))
    },
    [tags, onChange]
  )

  const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
    if (e.key === 'Enter') {
      e.preventDefault()
      if (selectedIndex >= 0 && suggestions[selectedIndex]) {
        addTag(suggestions[selectedIndex].name)
      } else if (inputValue.trim()) {
        addTag(inputValue)
      }
    } else if (e.key === 'Backspace' && !inputValue && tags.length > 0) {
      removeTag(tags[tags.length - 1])
    } else if (e.key === 'ArrowDown') {
      e.preventDefault()
      setSelectedIndex((prev) =>
        prev < suggestions.length - 1 ? prev + 1 : prev
      )
    } else if (e.key === 'ArrowUp') {
      e.preventDefault()
      setSelectedIndex((prev) => (prev > 0 ? prev - 1 : -1))
    } else if (e.key === 'Escape') {
      setShowSuggestions(false)
      setSelectedIndex(-1)
    } else if (e.key === ',' || e.key === ';' || e.key === 'Tab') {
      if (inputValue.trim()) {
        e.preventDefault()
        // Support multiple tags separated by commas or semicolons
        const parts = inputValue.split(/[,;]/).map(s => s.trim()).filter(Boolean)
        for (const part of parts) {
          addTag(part)
        }
      }
    }
  }

  return (
    <div ref={wrapperRef} className="relative">
      <div
        className={cn(
          'flex flex-wrap gap-1.5 rounded-xl border px-2 py-1.5',
          'bg-card text-foreground',
          'focus-within:border-primary focus-within:ring-1 focus-within:ring-primary/20',
          disabled ? 'cursor-not-allowed opacity-50' : '',
          'border-border'
        )}
        onClick={() => inputRef.current?.focus()}
      >
        {/* Tag chips */}
        {tags.map((tag) => (
          <span
            key={tag}
            className={cn(
              'inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-xs',
              'bg-accent text-muted-foreground'
            )}
          >
            {tag}
            {!disabled && (
              <button
                type="button"
                onClick={(e) => {
                  e.stopPropagation()
                  removeTag(tag)
                }}
                className="rounded-full p-0.5 hover:bg-accent"
              >
                <X className="h-3 w-3" />
              </button>
            )}
          </span>
        ))}

        {/* Input field */}
        {tags.length < maxTags && (
          <input
            ref={inputRef}
            type="text"
            value={inputValue}
            onChange={(e) => {
              const val = e.target.value
              // If pasted text contains delimiters, split into tags immediately
              if (val.includes(',') || val.includes(';')) {
                const parts = val.split(/[,;]/).map(s => s.trim()).filter(Boolean)
                const last = parts.pop()
                for (const part of parts) {
                  addTag(part)
                }
                setInputValue(last || '')
              } else {
                setInputValue(val)
              }
            }}
            onKeyDown={handleKeyDown}
            onFocus={() => {
              if (inputValue.length >= 1 && suggestions.length > 0) {
                setShowSuggestions(true)
              }
            }}
            placeholder={tags.length === 0 ? placeholder : ''}
            disabled={disabled}
            className={cn(
              'flex-1 min-w-[80px] border-0 bg-transparent px-1 py-0.5 text-sm text-foreground',
              'placeholder:text-muted-foreground',
              'focus:outline-none focus:ring-0'
            )}
          />
        )}
      </div>

      {/* Suggestions dropdown */}
      {showSuggestions && suggestions.length > 0 && (
        <div
          className={cn(
            'absolute z-10 mt-1 w-full rounded-xl border border-border',
            'bg-card shadow-lg'
          )}
        >
          {suggestions.map((suggestion, index) => (
            <button
              key={suggestion.id}
              type="button"
              onClick={() => addTag(suggestion.name)}
              className={cn(
                'flex w-full items-center justify-between px-3 py-2 text-sm text-muted-foreground',
                'hover:bg-accent',
                index === selectedIndex && 'bg-accent'
              )}
            >
              <span>{suggestion.name}</span>
              <span className="text-xs text-muted-foreground">
                {suggestion.usage_count} trees
              </span>
            </button>
          ))}
          {inputValue.trim() &&
            !suggestions.some(
              (s) => s.name.toLowerCase() === inputValue.toLowerCase()
            ) && (
              <button
                type="button"
                onClick={() => addTag(inputValue)}
                className={cn(
                  'flex w-full items-center gap-2 border-t border-border px-3 py-2 text-sm',
                  'hover:bg-accent text-foreground'
                )}
              >
                <Plus className="h-4 w-4" />
                Create "{inputValue}"
              </button>
            )}
        </div>
      )}

      {/* Helper text */}
      <p className="mt-1 text-xs text-muted-foreground">
        {tags.length}/{maxTags} tags. Press Enter, Tab, comma, or semicolon to add.
      </p>
    </div>
  )
}

export default TagInput
