import { useEffect, useRef, useState, type KeyboardEvent } from 'react';
import { extractApiError } from '@/api/client';
import type { MitreTechnique } from '@/api/types';
import { useMitreSearch } from '@/hooks/useMitre';

interface MitreTechniquePickerProps {
  onSelect: (technique: MitreTechnique) => void;
  disabled?: boolean;
}

const DEBOUNCE_MS = 200;

export function MitreTechniquePicker({
  onSelect,
  disabled = false,
}: MitreTechniquePickerProps): JSX.Element {
  const [inputValue, setInputValue] = useState('');
  const [query, setQuery] = useState('');
  const [open, setOpen] = useState(false);
  const [activeIndex, setActiveIndex] = useState(-1);
  const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);
  const containerRef = useRef<HTMLDivElement>(null);
  const listRef = useRef<HTMLUListElement>(null);

  const { data: results, isFetching, isError, error } = useMitreSearch(query, open);

  const items = results ?? [];

  const handleInputChange = (value: string) => {
    setInputValue(value);
    setOpen(true);
    setActiveIndex(-1);

    if (debounceRef.current) clearTimeout(debounceRef.current);
    debounceRef.current = setTimeout(() => {
      setQuery(value);
    }, DEBOUNCE_MS);
  };

  const selectItem = (item: MitreTechnique) => {
    onSelect(item);
    // Reset to empty after selection — parent handles append + dedup
    setInputValue('');
    setQuery('');
    setOpen(false);
    setActiveIndex(-1);
  };

  const handleKeyDown = (e: KeyboardEvent<HTMLInputElement>) => {
    if (!open || items.length === 0) {
      if (e.key === 'Escape') setOpen(false);
      return;
    }
    if (e.key === 'ArrowDown') {
      e.preventDefault();
      setActiveIndex((i) => Math.min(i + 1, items.length - 1));
    } else if (e.key === 'ArrowUp') {
      e.preventDefault();
      setActiveIndex((i) => Math.max(i - 1, 0));
    } else if (e.key === 'Enter') {
      e.preventDefault();
      if (activeIndex >= 0 && items[activeIndex]) {
        selectItem(items[activeIndex]);
      }
    } else if (e.key === 'Escape') {
      setOpen(false);
      setActiveIndex(-1);
    }
  };

  useEffect(() => {
    if (activeIndex >= 0 && listRef.current) {
      const el = listRef.current.children[activeIndex] as HTMLElement | undefined;
      el?.scrollIntoView?.({ block: 'nearest' });
    }
  }, [activeIndex]);

  useEffect(() => {
    const onPointerDown = (e: PointerEvent) => {
      if (containerRef.current && !containerRef.current.contains(e.target as Node)) {
        setOpen(false);
      }
    };
    document.addEventListener('pointerdown', onPointerDown);
    return () => document.removeEventListener('pointerdown', onPointerDown);
  }, []);

  const listboxId = 'mitre-picker-listbox';

  return (
    <div ref={containerRef} className="relative">
      <input
        type="text"
        role="combobox"
        aria-expanded={open}
        aria-controls={listboxId}
        aria-activedescendant={activeIndex >= 0 ? `mitre-option-${activeIndex}` : undefined}
        aria-label="Search MITRE technique"
        className="text-input"
        value={inputValue}
        onChange={(e) => handleInputChange(e.target.value)}
        onFocus={() => setOpen(true)}
        onKeyDown={handleKeyDown}
        disabled={disabled}
        placeholder="Search by ID or name (e.g. T1059)"
        autoComplete="off"
      />

      {open && (
        <div className="absolute z-20 w-full mt-xxs bg-paper border border-steel rounded-none overflow-hidden">
          {isFetching && (
            <div className="px-md py-sm text-[14px] text-graphite">Searching…</div>
          )}

          {isError && !isFetching && (
            <div className="px-md py-sm text-[14px] text-bloom-deep" role="alert">
              {extractApiError(error, 'MITRE search unavailable')}
            </div>
          )}

          {!isFetching && !isError && items.length === 0 && query.trim().length > 0 && (
            <div className="px-md py-sm text-[14px] text-graphite">No results</div>
          )}

          {!isFetching && items.length > 0 && (
            <ul
              id={listboxId}
              ref={listRef}
              role="listbox"
              aria-label="MITRE techniques"
              className="max-h-64 overflow-y-auto"
            >
              {items.map((item, i) => (
                <li
                  key={item.id}
                  id={`mitre-option-${i}`}
                  role="option"
                  aria-selected={i === activeIndex}
                  className={`px-md py-sm text-[14px] cursor-pointer select-none ${
                    i === activeIndex ? 'bg-primary-soft text-ink' : 'text-ink hover:bg-cloud'
                  }`}
                  onPointerDown={(e) => {
                    e.preventDefault();
                    selectItem(item);
                  }}
                >
                  <span className="font-mono font-medium">{item.id}</span>
                  <span className="text-charcoal"> — {item.name}</span>
                  {item.tactics.length > 0 && (
                    <span className="font-mono text-graphite"> ({item.tactics[0]})</span>
                  )}
                </li>
              ))}
            </ul>
          )}
        </div>
      )}
    </div>
  );
}
