import type { ChangeEvent, KeyboardEvent } from 'react'
import { cn } from '@langgenius/dify-ui/cn'
import { toast } from '@langgenius/dify-ui/toast'
import { useCallback, useState } from 'react'
import { useTranslation } from 'react-i18next'

type TagInputProps = {
  items: string[]
  onChange: (items: string[]) => void
  disableRemove?: boolean
  disableAdd?: boolean
  customizedConfirmKey?: 'Enter' | 'Tab'
  isInWorkflow?: boolean
  placeholder?: string
  required?: boolean
  inputClassName?: string
}

const TagInput = ({
  items,
  onChange,
  disableAdd,
  disableRemove,
  customizedConfirmKey = 'Enter',
  isInWorkflow,
  placeholder,
  required = false,
  inputClassName,
}: TagInputProps) => {
  const { t } = useTranslation()
  const [value, setValue] = useState('')
  const [focused, setFocused] = useState(false)
  const isSpecialMode = customizedConfirmKey === 'Tab'
  const inputPlaceholder =
    placeholder ||
    (isSpecialMode
      ? t(($) => $['model.params.stop_sequencesPlaceholder'], { ns: 'common' })
      : t(($) => $['segment.addKeyWord'], { ns: 'datasetDocuments' }))
  const handleRemove = (index: number) => {
    const copyItems = [...items]
    copyItems.splice(index, 1)
    onChange(copyItems)
  }
  const handleNewTag = useCallback(
    (value: string) => {
      const valueTrimmed = value.trim()
      if (!valueTrimmed) {
        if (required) toast.error(t(($) => $['segment.keywordEmpty'], { ns: 'datasetDocuments' }))
        return
      }
      if (items.find((item) => item === valueTrimmed)) {
        toast.error(t(($) => $['segment.keywordDuplicate'], { ns: 'datasetDocuments' }))
        return
      }
      if (valueTrimmed.length > 20) {
        toast.error(t(($) => $['segment.keywordError'], { ns: 'datasetDocuments' }))
        return
      }
      onChange([...items, valueTrimmed])
      setTimeout(() => {
        setValue('')
      })
    },
    [items, onChange, t, required],
  )
  const handleKeyDown = (e: KeyboardEvent) => {
    if (isSpecialMode && e.key === 'Enter') setValue(`${value}↵`)
    if (e.key === customizedConfirmKey) {
      if (isSpecialMode) e.preventDefault()
      handleNewTag(value)
    }
  }
  const handleBlur = () => {
    handleNewTag(value)
    setFocused(false)
  }
  return (
    <div
      className={cn(
        'flex flex-wrap',
        !isInWorkflow && 'min-w-[200px]',
        isSpecialMode ? 'rounded-lg bg-components-input-bg-normal pb-1 pl-1' : '',
      )}
    >
      {(items || []).map((item, index) => (
        <div
          key={item}
          className={cn(
            'mt-1 mr-1 flex items-center rounded-md border border-divider-deep bg-components-badge-white-to-dark py-1 pr-1 pl-1.5 system-xs-regular text-text-secondary',
          )}
        >
          {item}
          {!disableRemove && (
            <button
              type="button"
              aria-label={`${t(($) => $['operation.remove'], { ns: 'common' })} ${item}`}
              className="flex size-4 cursor-pointer items-center justify-center border-none bg-transparent p-0 focus-visible:ring-1 focus-visible:ring-components-input-border-active focus-visible:outline-hidden"
              onClick={() => handleRemove(index)}
            >
              <span
                className="ml-0.5 i-ri-close-line size-3.5 text-text-tertiary"
                aria-hidden="true"
              />
            </button>
          )}
        </div>
      ))}
      {!disableAdd && (
        <div
          className={cn(
            'group/tag-add mt-1 flex items-center gap-x-0.5',
            !isSpecialMode ? 'rounded-md border border-dashed border-divider-deep px-1.5' : '',
          )}
        >
          {!isSpecialMode && !focused && (
            <span className="i-ri-add-line size-3.5 text-text-placeholder group-hover/tag-add:text-text-secondary" />
          )}
          <span
            data-input-value={value || inputPlaceholder}
            className={cn(
              !isInWorkflow && 'max-w-[300px]',
              isInWorkflow && 'max-w-[146px]',
              'grid overflow-hidden rounded-md py-1 system-xs-regular after:invisible after:col-start-1 after:row-start-1 after:whitespace-pre after:content-[attr(data-input-value)]',
              isSpecialMode && 'border border-transparent px-1.5',
              focused && isSpecialMode && 'border-dashed border-divider-deep',
            )}
          >
            <input
              className={cn(
                'col-start-1 row-start-1 w-full min-w-0 appearance-none text-text-primary caret-[#295EFF] outline-hidden placeholder:text-text-placeholder group-hover/tag-add:placeholder:text-text-secondary',
                isSpecialMode ? 'bg-transparent' : '',
                inputClassName,
              )}
              onFocus={() => setFocused(true)}
              onBlur={handleBlur}
              value={value}
              onChange={(e: ChangeEvent<HTMLInputElement>) => {
                setValue(e.target.value)
              }}
              onKeyDown={handleKeyDown}
              placeholder={inputPlaceholder}
            />
          </span>
        </div>
      )}
    </div>
  )
}
export default TagInput
