import { useEffect, useMemo, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import {
  buildCommands, filterCommands, groupCommands,
  type CommandContext, type CommandItem,
} from '../../lib/command-palette';

interface Props {
  open: boolean;
  onClose: () => void;
  ctx: CommandContext;
}

export function CommandPalette({ open, onClose, ctx }: Props) {
  const { t } = useTranslation('layout');
  const dialogRef = useRef<HTMLDialogElement>(null);
  const inputRef = useRef<HTMLInputElement>(null);
  const openerRef = useRef<Element | null>(null);
  const [query, setQuery] = useState('');
  const [highlight, setHighlight] = useState(0);

  const allCommands = useMemo(() => buildCommands(ctx), [ctx]);
  const results = useMemo(() => filterCommands(allCommands, query), [allCommands, query]);
  const groups = useMemo(() => groupCommands(results), [results]);

  useEffect(() => {
    const dlg = dialogRef.current;
    if (!dlg) return;
    if (open && !dlg.open) {
      openerRef.current = document.activeElement;
      setQuery('');
      setHighlight(0);
      dlg.showModal();
      inputRef.current?.focus();
    } else if (!open && dlg.open) {
      dlg.close();
      const o = openerRef.current;
      if (o instanceof HTMLElement && o.isConnected) o.focus();
      else document.body.focus();
    }
  }, [open]);

  useEffect(() => {
    const dlg = dialogRef.current;
    if (!dlg) return;
    const onCancel = (e: Event) => { e.preventDefault(); onClose(); };
    const onClick = (e: MouseEvent) => { if (e.target === dlg) onClose(); };
    dlg.addEventListener('cancel', onCancel);
    dlg.addEventListener('click', onClick);
    return () => { dlg.removeEventListener('cancel', onCancel); dlg.removeEventListener('click', onClick); };
  }, [onClose]);

  useEffect(() => { setHighlight(0); }, [query]);

  const flat = results;
  const highlightedId = flat[highlight]?.id;

  const onKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
    if (e.key === 'ArrowDown') { e.preventDefault(); setHighlight((h) => Math.min(h + 1, flat.length - 1)); }
    else if (e.key === 'ArrowUp') { e.preventDefault(); setHighlight((h) => Math.max(h - 1, 0)); }
    else if (e.key === 'Enter') {
      e.preventDefault();
      const item = flat[highlight];
      if (item) { item.run(); onClose(); }
    }
  };

  useEffect(() => {
    if (!highlightedId) return;
    document.getElementById(`cmdk-opt-${highlightedId}`)?.scrollIntoView({ block: 'nearest' });
  }, [highlightedId]);

  return (
    <dialog
      ref={dialogRef}
      aria-label={t('commandPalette.label')}
      className="m-0 mt-[12vh] mx-auto w-[min(560px,92vw)] rounded-xl border border-hairline bg-surface text-ink shadow-2xl p-0 backdrop:bg-black/40"
    >
      <div className="p-2 border-b border-hairline">
        <input
          ref={inputRef}
          role="combobox"
          aria-expanded="true"
          aria-controls="cmdk-listbox"
          aria-label={t('commandPalette.searchLabel')}
          aria-activedescendant={highlightedId ? `cmdk-opt-${highlightedId}` : undefined}
          value={query}
          onChange={(e) => setQuery(e.target.value)}
          onKeyDown={onKeyDown}
          placeholder={t('commandPalette.searchPlaceholder')}
          className="w-full h-9 px-2 bg-transparent outline-none text-sm"
        />
      </div>
      <div id="cmdk-listbox" role="listbox" className="max-h-[52vh] overflow-y-auto p-1">
        {flat.length === 0 && <div role="status" className="px-3 py-6 text-center text-sm text-muted">{t('commandPalette.empty')}</div>}
        {groups.map((g) => (
          <div key={g.group} role="group" aria-label={g.label}>
            <div className="section-label px-2 pt-2 pb-1">{g.label}</div>
            {g.items.map((item: CommandItem) => {
              const active = item.id === highlightedId;
              return (
                <div
                  key={item.id}
                  id={`cmdk-opt-${item.id}`}
                  role="option"
                  aria-selected={active}
                  onMouseMove={() => setHighlight(flat.indexOf(item))}
                  onClick={() => { item.run(); onClose(); }}
                  className={`flex items-center justify-between gap-2 px-2.5 h-9 rounded-md cursor-pointer text-sm ${
                    active ? 'bg-surface-2 text-ink' : 'text-slate-600'
                  }`}
                >
                  <span className="truncate">{item.label}</span>
                  {item.hint && <span className="text-2xs text-muted flex-shrink-0">{item.hint}</span>}
                </div>
              );
            })}
          </div>
        ))}
      </div>
    </dialog>
  );
}
