import { useRef } from 'react';
import { createPortal } from 'react-dom';
import type React from 'react';
import type { SearchResult } from '../../hooks/useLocationSearch';
import { useDropdownPosition } from '../../hooks/useDropdownPosition';
import { SearchIcon } from './icons/SearchIcon';
import { MapPinIcon } from './icons/MapPinIcon';

interface SearchHook {
  query: string;
  results: SearchResult[];
  activeIndex: number;
  setActiveIndex: (idx: number) => void;
  open: boolean;
  setOpen: (open: boolean) => void;
  handleInputChange: (value: string) => void;
  handleKeyDown: (e: React.KeyboardEvent, onSelect: (result: SearchResult) => void) => void;
}

interface PlaceSearchInputProps {
  search: SearchHook;
  onSelect: (result: SearchResult) => void;
  loading?: boolean;
  placeholder?: string;
  size?: 'sm' | 'xs';
  inputClassName?: string;
  inputRef?: React.Ref<HTMLInputElement>;
  onInputChange?: () => void;
  portal?: boolean;
}

export function PlaceSearchInput({
  search,
  onSelect,
  loading,
  placeholder,
  size = 'sm',
  inputClassName,
  inputRef,
  onInputChange,
  portal,
}: PlaceSearchInputProps) {
  const sm = size === 'sm';
  const iconSize = sm ? 'w-4 h-4' : 'w-3 h-3';
  const spinnerSize = sm ? 'w-4 h-4' : 'w-3 h-3';
  const wrapperRef = useRef<HTMLDivElement>(null);
  const dropdownPos = useDropdownPosition(wrapperRef, portal ? search.open : false);

  const showDropdown = search.open && search.results.length > 0;

  const dropdown = showDropdown && (
    <div
      className={`bg-white dark:bg-warm-800 rounded shadow-lg border border-warm-200 dark:border-warm-700 ${sm ? 'max-h-64' : 'max-h-48'} overflow-y-auto`}
      style={
        portal && dropdownPos
          ? {
              position: 'fixed',
              top: dropdownPos.top,
              left: dropdownPos.left,
              width: dropdownPos.width,
              zIndex: 50,
            }
          : undefined
      }
    >
      {search.results.map((result, idx) => (
        <button
          key={
            result.type === 'postcode' ? `pc-${result.label}` : `pl-${result.name}-${result.lat}`
          }
          type="button"
          className={`w-full text-left flex items-center cursor-pointer ${
            sm ? 'px-3 py-2 gap-2 text-sm' : 'px-2 py-1.5 gap-1.5 text-xs'
          } ${
            idx === search.activeIndex
              ? 'bg-teal-50 dark:bg-teal-900/30'
              : 'hover:bg-warm-50 dark:hover:bg-warm-700'
          }`}
          onMouseEnter={() => search.setActiveIndex(idx)}
          onMouseDown={(e) => {
            e.preventDefault();
            onSelect(result);
          }}
        >
          {result.type === 'postcode' ? (
            <>
              <SearchIcon className={`${iconSize} text-warm-400 dark:text-warm-500 shrink-0`} />
              <span className="text-warm-700 dark:text-warm-200">{result.label}</span>
            </>
          ) : (
            <>
              <MapPinIcon className={`${iconSize} text-warm-400 dark:text-warm-500 shrink-0`} />
              <span className="text-warm-700 dark:text-warm-200">
                {result.name}
                {result.city && (
                  <span className="text-warm-400 dark:text-warm-500"> ({result.city})</span>
                )}
              </span>
            </>
          )}
        </button>
      ))}
    </div>
  );

  return (
    <div ref={wrapperRef} className="relative flex-1 min-w-0">
      <input
        ref={inputRef}
        type="text"
        value={search.query}
        onChange={(e) => {
          search.handleInputChange(e.target.value);
          onInputChange?.();
        }}
        onFocus={() => {
          if (search.results.length > 0) search.setOpen(true);
        }}
        onKeyDown={(e) => search.handleKeyDown(e, onSelect)}
        placeholder={placeholder}
        className={inputClassName}
      />

      {loading && (
        <div
          className={`absolute right-2 top-1/2 -translate-y-1/2 ${spinnerSize} border-2 border-warm-300 dark:border-warm-600 border-t-teal-500 rounded-full animate-spin`}
        />
      )}

      {showDropdown &&
        (portal ? (
          createPortal(dropdown, document.body)
        ) : (
          <div className="absolute top-full left-0 right-0 mt-1 z-20">{dropdown}</div>
        ))}
    </div>
  );
}
