import * as React from 'react'
import { CheckIcon, CaretDownIcon } from '@phosphor-icons/react'
import * as PopoverPrimitive from '@radix-ui/react-popover'
import { Popover, PopoverTrigger, PopoverContent } from './popover'
import { FieldLabel, FieldHint, FieldError } from './field'
import { Badge } from './badge'
import { cn } from '@/lib/utils'

/**
 * MultiSelect — popover с inline checkboxes. Замена @nstart/ui MultiSelect.
 *
 * <p>Trigger показывает count selected + первые 2 selected labels.
 * Popover — список с checkboxes. Click toggle. Поиск НЕ implemented (handoff
 * MultiSelect не требует) — для search-heavy lists используй cmdk Combobox
 * (Stage 3.8b TODO).
 *
 * <p>API: options [{value, label}], value string[], onChange (ids: string[]).
 */

/** nstart-compat: {id, label}. Use `id` key. */
export type MultiSelectOption = {
  id: string
  label: React.ReactNode
  /** Alias of `id`. */
  value?: string
}

export type MultiSelectProps = {
  label?: React.ReactNode
  hint?: React.ReactNode
  error?: React.ReactNode
  required?: boolean
  options: MultiSelectOption[]
  value: string[]
  onChange: (next: string[]) => void
  placeholder?: string
  disabled?: boolean
  /** Wrapper className. */
  rootClassName?: string
  /** Compact display (no badges, just count). */
  compact?: boolean
}

export function MultiSelect({
  label,
  hint,
  error,
  required,
  options,
  value,
  onChange,
  placeholder,
  disabled,
  rootClassName,
  compact,
}: MultiSelectProps) {
  const autoId = React.useId()
  const triggerId = autoId
  const hintId = hint ? `${triggerId}-hint` : undefined
  const errorId = error ? `${triggerId}-error` : undefined

  const valueSet = React.useMemo(() => new Set(value), [value])
  const toggle = (id: string) => {
    const next = new Set(valueSet)
    if (next.has(id)) next.delete(id)
    else next.add(id)
    onChange(Array.from(next))
  }

  const selectedLabels = options
    .filter((o) => valueSet.has(o.id ?? o.value ?? ''))
    .map((o) => o.label)

  return (
    <div className={cn('flex flex-col gap-1', rootClassName)}>
      {label && (
        <FieldLabel htmlFor={triggerId} required={required}>
          {label}
        </FieldLabel>
      )}
      <Popover>
        <PopoverTrigger asChild>
          <button
            type="button"
            id={triggerId}
            disabled={disabled}
            aria-invalid={error ? true : undefined}
            aria-describedby={[hintId, errorId].filter(Boolean).join(' ') || undefined}
            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',
              error && 'border-pink focus-visible:ring-pink/40',
            )}
          >
            <span className="flex-1 min-w-0 flex items-center gap-1.5 overflow-hidden">
              {selectedLabels.length === 0 ? (
                <span className="text-mute truncate">{placeholder ?? '—'}</span>
              ) : compact ? (
                <span className="text-mono">
                  {selectedLabels.length} / {options.length}
                </span>
              ) : selectedLabels.length <= 2 ? (
                selectedLabels.map((lbl, i) => (
                  <Badge key={i} variant="info">
                    {lbl}
                  </Badge>
                ))
              ) : (
                <>
                  <Badge variant="info">{selectedLabels[0]}</Badge>
                  <Badge variant="info">+{selectedLabels.length - 1}</Badge>
                </>
              )}
            </span>
            <CaretDownIcon size={14} weight="bold" className="shrink-0 text-mute" />
          </button>
        </PopoverTrigger>
        <PopoverContent align="start" className="p-1 min-w-[var(--radix-popover-trigger-width)]">
          <PopoverPrimitive.Close className="hidden" />
          <ul role="listbox" aria-multiselectable className="max-h-64 overflow-y-auto">
            {options.map((opt) => {
              const checked = valueSet.has((opt.id ?? opt.value ?? ''))
              return (
                <li
                  key={(opt.id ?? opt.value ?? '')}
                  role="option"
                  aria-selected={checked}
                  tabIndex={0}
                  onClick={() => toggle((opt.id ?? opt.value ?? ''))}
                  onKeyDown={(e) => {
                    if (e.key === 'Enter' || e.key === ' ') {
                      e.preventDefault()
                      toggle((opt.id ?? opt.value ?? ''))
                    }
                  }}
                  className={cn(
                    'flex items-center gap-2 px-2.5 py-1.5 rounded-sm cursor-pointer text-body',
                    'hover:bg-surface-2 focus:bg-surface-2 focus:outline-none',
                    checked && 'text-ink',
                  )}
                >
                  <span
                    className={cn(
                      'inline-flex items-center justify-center size-4 rounded-sm border',
                      checked
                        ? 'bg-accent border-accent text-on-accent'
                        : 'border-line-2 bg-surface',
                    )}
                    aria-hidden="true"
                  >
                    {checked && <CheckIcon size={10} weight="bold" />}
                  </span>
                  <span className="flex-1 truncate">{opt.label}</span>
                </li>
              )
            })}
          </ul>
        </PopoverContent>
      </Popover>
      {hint && !error && <FieldHint id={hintId}>{hint}</FieldHint>}
      {error && <FieldError id={errorId}>{error}</FieldError>}
    </div>
  )
}
