'use client';

import { cn } from '@lib/utils';
import { CaretDownIcon, MagnifyingGlassIcon } from '@phosphor-icons/react';
import { useCallback, useEffect, useRef, useState } from 'react';

type SelectUserItem = {
  id: string;
  name: string;
  email: string;
};

const userLabel = (u: { name: string; email: string }) =>
  `${u.name} - ${u.email}`;

type SelectUserProps = {
  value: string;
  onValueChange: (userId: string) => void;
  values: SelectUserItem[];
  placeholder?: string;
  /** Khi truyền cùng onKeywordChange: tìm kiếm theo API (keyword gửi lên server) */
  keyword?: string;
  onKeywordChange?: (value: string) => void;
  searchPlaceholder?: string;
  name?: string;
  id?: string;
  'aria-invalid'?: boolean;
  disabled?: boolean;
  className?: string;
  selectKey?: 'id' | 'email';
};

export function SelectUser({
  value,
  onValueChange,
  values,
  placeholder,
  keyword,
  onKeywordChange,
  searchPlaceholder = 'Tìm theo tên hoặc email...',
  name,
  id,
  'aria-invalid': ariaInvalid,
  disabled = false,
  className,
  selectKey = 'id',
}: SelectUserProps) {
  const [open, setOpen] = useState(false);
  const [localQuery, setLocalQuery] = useState('');
  const wrapperRef = useRef<HTMLDivElement>(null);
  const searchInputRef = useRef<HTMLInputElement>(null);

  const useServerSearch = keyword !== undefined && onKeywordChange != null;
  const searchValue = useServerSearch ? keyword : localQuery;
  const setSearchValue = useServerSearch ? onKeywordChange! : setLocalQuery;

  const selectedUser =
    value != null && value !== ''
      ? values.find((u) => u[selectKey] === value)
      : null;
  const displayValue = selectedUser ? userLabel(selectedUser) : '';

  const filtered = useServerSearch
    ? values
    : (() => {
        const q = localQuery.trim().toLowerCase();
        return q === ''
          ? values
          : values.filter(
              (u) =>
                u.name.toLowerCase().includes(q) ||
                u.email.toLowerCase().includes(q),
            );
      })();

  const close = useCallback(() => {
    setOpen(false);
    if (!useServerSearch) setLocalQuery('');
  }, [useServerSearch]);

  useEffect(() => {
    if (!open) return;
    searchInputRef.current?.focus();
  }, [open]);

  useEffect(() => {
    if (!open) return;
    const onMouseDown = (e: MouseEvent) => {
      if (
        wrapperRef.current &&
        !wrapperRef.current.contains(e.target as Node)
      ) {
        close();
      }
    };
    document.addEventListener('mousedown', onMouseDown);
    return () => document.removeEventListener('mousedown', onMouseDown);
  }, [open, close]);

  const handleSelect = (userId: string) => {
    onValueChange(userId);
    close();
  };

  const controlId = id ?? name;
  const listboxId = controlId ? `${controlId}-listbox` : undefined;

  return (
    <div ref={wrapperRef} className={cn('relative', className)}>
      {name != null && (
        <input type="hidden" name={name} value={value} readOnly />
      )}
      <div
        role="combobox"
        aria-expanded={open}
        aria-haspopup="listbox"
        aria-invalid={ariaInvalid}
        aria-controls={open ? listboxId : undefined}
        aria-disabled={disabled}
        id={controlId}
        className={cn(
          'border-input bg-input/20 dark:bg-input/30 flex h-7 w-full cursor-pointer items-center gap-1.5 rounded-md border px-2 py-0.5 text-xs/relaxed outline-none transition-colors focus-visible:ring-2 focus-visible:ring-ring/30 aria-invalid:border-destructive aria-invalid:ring-destructive/20 disabled:cursor-not-allowed disabled:opacity-50',
        )}
        onClick={() => !disabled && setOpen((o) => !o)}
      >
        <span className="min-w-0 flex-1 truncate text-left">
          {displayValue || (
            <span className="text-muted-foreground">{placeholder}</span>
          )}
        </span>
        <CaretDownIcon
          className={cn(
            'size-3.5 shrink-0 text-muted-foreground transition-transform',
            open && 'rotate-180',
          )}
        />
      </div>
      {open && (
        <div
          id={listboxId}
          role="listbox"
          className="border-input bg-popover text-popover-foreground absolute top-full z-50 mt-1 max-h-60 w-full min-w-(--radix-popper-anchor-width) overflow-hidden rounded-lg border shadow-md"
        >
          <div className="border-input flex items-center gap-1 border-b px-2 py-1">
            <MagnifyingGlassIcon className="text-muted-foreground size-3.5 shrink-0" />
            <input
              ref={searchInputRef}
              type="search"
              autoComplete="off"
              placeholder={searchPlaceholder}
              value={searchValue}
              onChange={(e) => setSearchValue(e.target.value)}
              onKeyDown={(e) => e.stopPropagation()}
              className="min-w-0 flex-1 bg-transparent py-1 text-xs outline-none placeholder:text-muted-foreground"
            />
          </div>
          <div className="max-h-52 overflow-y-auto p-1">
            {filtered.length === 0 ? (
              <div className="text-muted-foreground py-4 text-center text-xs">
                Không có kết quả
              </div>
            ) : (
              filtered.map((u) => (
                <button
                  key={u.id}
                  type="button"
                  role="option"
                  aria-selected={value === u[selectKey]}
                  className={cn(
                    'hover:bg-accent hover:text-accent-foreground flex w-full cursor-pointer items-center rounded-md px-2 py-1.5 text-left text-xs/relaxed outline-none',
                    value === u[selectKey] &&
                      'bg-accent text-accent-foreground',
                  )}
                  onClick={(e) => {
                    e.preventDefault();
                    e.stopPropagation();
                    handleSelect(u[selectKey]);
                  }}
                >
                  {userLabel(u)}
                </button>
              ))
            )}
          </div>
        </div>
      )}
    </div>
  );
}
