import * as React from 'react'
import { useMemo, useState } from 'react'
import { CaretDownIcon, MagnifyingGlassIcon, UserIcon, XIcon } from '@phosphor-icons/react'
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from 'cmdk'
import { Popover, PopoverTrigger, PopoverContent, FieldLabel } from '@/ui'
import { useAllUsers, type UserListItem } from '@/api/queries'
import { cn } from '@/lib/utils'

/**
 * Single-value user picker — cmdk-powered combobox для audit-фильтра
 * «Пользователь». Заменяет ручной TextInput на typeahead по username/email/UUID.
 *
 * <p>Источник: GET /api/v1/admin/users (cached user_display table).
 * INTERNAL+ scope требуется на backend; non-INTERNAL получит пустой
 * список и падает на input fallback (поле остаётся редактируемым).
 *
 * <p>UX: trigger показывает username (или UUID prefix как fallback);
 * X сбрасывает selection inline. В popover'е — поиск по subname/email/UUID.
 */

const labelFor = (u: UserListItem): string =>
  u.preferredUsername || u.name || `${u.sub.slice(0, 8)}…`

const secondaryFor = (u: UserListItem): string | null => {
  if (u.email && u.email !== u.preferredUsername) return u.email
  return null
}

export type UserPickerProps = {
  value: string | undefined
  onChange: (sub: string | undefined) => void
  label?: React.ReactNode
  placeholder?: string
  disabled?: boolean
}

export function UserPicker({ value, onChange, label, placeholder, disabled }: UserPickerProps) {
  const [open, setOpen] = useState(false)
  const usersQ = useAllUsers()

  const usersBySub = useMemo(() => {
    const m = new Map<string, UserListItem>()
    for (const u of usersQ.data ?? []) m.set(u.sub, u)
    return m
  }, [usersQ.data])

  const selected = value ? usersBySub.get(value) : undefined
  const triggerLabel = useMemo(() => {
    if (!value) return placeholder ?? 'Любой'
    if (selected) return labelFor(selected)
    // Value есть, но юзера нет в кеше — показываем UUID prefix.
    return `${value.slice(0, 8)}…`
  }, [value, selected, placeholder])

  // Поиск: substring по preferredUsername / name / email / sub. cmdk
  // делает client-side фильтрацию по value атрибуту CommandItem'а;
  // концатенируем все поля в один searchable string.
  const searchableValue = (u: UserListItem): string =>
    [u.preferredUsername, u.name, u.email, u.sub].filter(Boolean).join(' ')

  const clear = (e: React.MouseEvent) => {
    e.stopPropagation()
    onChange(undefined)
  }

  return (
    <div className="flex flex-col gap-1">
      {label && <FieldLabel>{label}</FieldLabel>}
      <Popover open={open} onOpenChange={setOpen}>
        <PopoverTrigger asChild>
          <button
            type="button"
            disabled={disabled}
            className={cn(
              'flex items-center justify-between gap-2 h-9 w-full rounded-md border border-line bg-surface px-3 text-body text-ink',
              'hover:border-line-2 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',
              'disabled:cursor-not-allowed disabled:opacity-50',
            )}
          >
            <span className="flex items-center gap-2 flex-1 min-w-0">
              <UserIcon size={14} weight="regular" className="shrink-0 text-mute" />
              <span className={cn('truncate text-left', !value && 'text-mute')}>
                {triggerLabel}
              </span>
            </span>
            <span className="flex items-center gap-1 shrink-0">
              {value && (
                <button
                  type="button"
                  aria-label="Сбросить пользователя"
                  onClick={clear}
                  className="p-0.5 rounded hover:bg-line/40 text-mute hover:text-ink"
                >
                  <XIcon size={12} weight="bold" />
                </button>
              )}
              <CaretDownIcon size={12} weight="regular" className="text-mute" />
            </span>
          </button>
        </PopoverTrigger>
        <PopoverContent
          align="start"
          className="p-0 w-[min(95vw,360px)]"
        >
          <Command className="bg-surface rounded-md">
            <div className="flex items-center gap-2 px-2 border-b border-line">
              <MagnifyingGlassIcon size={14} weight="regular" className="text-mute shrink-0" />
              <CommandInput
                placeholder="Поиск по имени, email или UUID…"
                className="h-9 w-full bg-transparent outline-none text-body text-ink placeholder:text-mute"
              />
            </div>
            <CommandList className="max-h-72 overflow-y-auto py-1">
              <CommandEmpty className="px-3 py-2 text-cell text-mute">
                {usersQ.isLoading ? 'Загрузка…' : 'Пользователи не найдены'}
              </CommandEmpty>
              <CommandGroup>
                {(usersQ.data ?? []).map((u) => {
                  const sec = secondaryFor(u)
                  return (
                    <CommandItem
                      key={u.sub}
                      value={searchableValue(u)}
                      onSelect={() => {
                        onChange(u.sub)
                        setOpen(false)
                      }}
                      className={cn(
                        'flex items-center gap-2 px-2.5 py-1.5 rounded cursor-pointer text-body',
                        value === u.sub
                          ? 'bg-accent-bg text-accent'
                          : 'text-ink hover:bg-surface-2 aria-selected:bg-surface-2',
                      )}
                    >
                      <UserIcon size={14} weight="regular" className="shrink-0 text-mute" />
                      <span className="flex-1 min-w-0">
                        <span className="block truncate">{labelFor(u)}</span>
                        {sec && (
                          <span className="block truncate text-cap text-mute">{sec}</span>
                        )}
                      </span>
                    </CommandItem>
                  )
                })}
              </CommandGroup>
            </CommandList>
          </Command>
        </PopoverContent>
      </Popover>
    </div>
  )
}
