import { useEffect, useRef, useState } from 'react'
import { useQuery } from '@tanstack/react-query'
import { Search, UserPlus, X } from 'lucide-react'
import { searchUsers } from '@/api/users'
import { Avatar } from '@/components/ui/Avatar'

/** Простая проверка формата email — не заменяет валидацию backend, только клиентская подсказка. */
const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/

/**
 * Выбранный участник конференции — зарегистрированный (`userId` заполнен,
 * `email` для него не всегда известен: `GET /users?q=` не возвращает email,
 * только `{id, display_name, avatar_url}`) или внешний гость (только `email`,
 * `userId` не заполнен).
 */
export interface SelectedParticipant {
  /** Стабильный идентификатор чипа — `userId` для зарегистрированных, email для внешних. */
  key: string
  userId?: string
  email?: string
  /** Что показывать в чипе/списке — имя для зарегистрированных, email для внешних. */
  displayName: string
  avatarUrl?: string | null
}

interface OrganizerChip {
  name: string
  email?: string
  avatarUrl?: string | null
}

interface ParticipantsPickerProps {
  participants: SelectedParticipant[]
  onChange: (next: SelectedParticipant[]) => void
  /** Организатор — показывается первым чипом без крестика удаления (не входит в редактируемый список). */
  organizer?: OrganizerChip | null
  disabled?: boolean
}

/**
 * Пикер участников конференции — новый UI-элемент, для
 * которого нет готового макета в `design/mockups/`; собран из уже
 * утверждённых паттернов дизайн-системы: чипы как у фильтров «Моих
 * конференций» (`.chip`), выпадающий список результатов — паттерн дроплиста
 * селекта (§4.16, `.vc-select-panel`/`.vc-select-option`), поле поиска — как
 * `.search-wrap` админки. Поиск зарегистрированных — debounce 300 мс; если
 * введённая строка похожа на email — параллельно предлагается добавить её
 * как внешнего участника (backend не отдаёт email по поиску, поэтому нельзя
 * достоверно исключить совпадение с уже найденным зарегистрированным).
 */
export function ParticipantsPicker({ participants, onChange, organizer, disabled }: ParticipantsPickerProps) {
  const [inputValue, setInputValue] = useState('')
  const [debounced, setDebounced] = useState('')
  const [open, setOpen] = useState(false)
  const rootRef = useRef<HTMLDivElement>(null)

  useEffect(() => {
    const timer = setTimeout(() => setDebounced(inputValue.trim()), 300)
    return () => clearTimeout(timer)
  }, [inputValue])

  const { data: results, isFetching } = useQuery({
    queryKey: ['users', 'search', debounced],
    queryFn: () => searchUsers(debounced, 8),
    enabled: debounced.length >= 2,
  })

  useEffect(() => {
    if (!open) return
    function handlePointerDown(event: MouseEvent) {
      if (rootRef.current && !rootRef.current.contains(event.target as Node)) setOpen(false)
    }
    document.addEventListener('mousedown', handlePointerDown)
    return () => document.removeEventListener('mousedown', handlePointerDown)
  }, [open])

  const selectedUserIds = new Set(participants.map((p) => p.userId).filter(Boolean))
  const selectedEmails = new Set(participants.map((p) => p.email?.toLowerCase()).filter(Boolean))
  const candidates = (results ?? []).filter((u) => !selectedUserIds.has(u.id))

  const trimmed = inputValue.trim()
  const isEmailLike = EMAIL_RE.test(trimmed)
  const canAddExternal = isEmailLike && !selectedEmails.has(trimmed.toLowerCase())

  function addRegistered(user: { id: string; display_name: string; avatar_url: string | null }) {
    onChange([...participants, { key: user.id, userId: user.id, displayName: user.display_name, avatarUrl: user.avatar_url }])
    setInputValue('')
    setDebounced('')
    setOpen(false)
  }

  function addExternal(email: string) {
    onChange([...participants, { key: email.toLowerCase(), email, displayName: email }])
    setInputValue('')
    setDebounced('')
    setOpen(false)
  }

  function removeParticipant(key: string) {
    onChange(participants.filter((p) => p.key !== key))
  }

  const showPanel = open && debounced.length >= 2 && (candidates.length > 0 || canAddExternal || isFetching)

  return (
    <div className="participants-picker" ref={rootRef}>
      {(organizer || participants.length > 0) && (
        <div className="participants-chips">
          {organizer && (
            <span className="participant-chip is-organizer">
              <Avatar name={organizer.name} avatarUrl={organizer.avatarUrl} size={20} />
              {organizer.name}
              <span className="participant-chip-role">организатор</span>
            </span>
          )}
          {participants.map((p) => (
            <span className="participant-chip" key={p.key}>
              <Avatar name={p.displayName} avatarUrl={p.avatarUrl} size={20} />
              {p.displayName}
              <button
                type="button"
                className="participant-chip-remove"
                aria-label={`Убрать участника: ${p.displayName}`}
                onClick={() => removeParticipant(p.key)}
                disabled={disabled}
              >
                <X style={{ width: 12, height: 12 }} aria-hidden="true" />
              </button>
            </span>
          ))}
        </div>
      )}

      <div className="participants-search-wrap">
        <Search className="icon" style={{ width: 16, height: 16 }} aria-hidden="true" />
        <input
          type="text"
          placeholder="Имя, email или адрес внешнего гостя…"
          value={inputValue}
          disabled={disabled}
          onChange={(e) => {
            setInputValue(e.target.value)
            setOpen(true)
          }}
          onFocus={() => setOpen(true)}
          onKeyDown={(e) => {
            if (e.key === 'Enter') {
              e.preventDefault()
              if (candidates.length === 1) addRegistered(candidates[0])
              else if (canAddExternal) addExternal(trimmed)
            } else if (e.key === 'Escape') {
              setOpen(false)
            }
          }}
        />
      </div>

      {showPanel && (
        <ul className="vc-select-panel participants-results">
          {isFetching && candidates.length === 0 && <li className="participants-results-hint">Ищем…</li>}
          {candidates.map((user) => (
            <li key={user.id} className="vc-select-option" onClick={() => addRegistered(user)}>
              <span className="participant-option-body">
                <Avatar name={user.display_name} avatarUrl={user.avatar_url} size={22} />
                {user.display_name}
              </span>
            </li>
          ))}
          {canAddExternal && (
            <li className="vc-select-option" onClick={() => addExternal(trimmed)}>
              <span className="participant-option-body">
                <UserPlus style={{ width: 16, height: 16 }} aria-hidden="true" />
                Добавить «{trimmed}» как внешнего участника
              </span>
            </li>
          )}
          {!isFetching && candidates.length === 0 && !canAddExternal && (
            <li className="participants-results-hint">Никого не нашли — введите email внешнего участника полностью</li>
          )}
        </ul>
      )}
    </div>
  )
}
