'use client';

import { useState, useRef, useEffect, useCallback } from 'react';
import { Loader2, AlertCircle, ChevronDown, Check, ArrowRightLeft } from 'lucide-react';
import { useI18n } from '@/lib/i18n';
import { cn } from '@/lib/utils';
import type { Language } from './types';

interface LanguageSelectorProps {
  sourceLang: string;
  targetLang: string;
  languages: Language[];
  isLoading?: boolean;
  error?: string | null;
  onSourceChange: (value: string) => void;
  onTargetChange: (value: string) => void;
}

/* ── Combobox dropdown with search ──────────────────────────────── */
function Combobox({
  value,
  options,
  includeAuto,
  autoLabel,
  placeholder,
  onChange,
  ariaLabel,
}: {
  value: string;
  options: Language[];
  includeAuto: boolean;
  autoLabel: string;
  placeholder: string;
  onChange: (code: string) => void;
  ariaLabel: string;
}) {
  const { t } = useI18n();
  const [open, setOpen] = useState(false);
  const [query, setQuery] = useState('');
  const ref = useRef<HTMLDivElement>(null);
  const inputRef = useRef<HTMLInputElement>(null);
  const triggerRef = useRef<HTMLButtonElement>(null);

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

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

  const closeAndRefocus = () => {
    setOpen(false);
    setQuery('');
    triggerRef.current?.focus();
  };

  const allOptions = includeAuto
    ? [{ code: 'auto', name: autoLabel }, ...options]
    : options;

  const q = query.toLowerCase().trim();
  const filtered = q
    ? allOptions.filter(l => l.name.toLowerCase().includes(q) || l.code.toLowerCase().includes(q))
    : allOptions;

  const label = value === 'auto' ? autoLabel : allOptions.find(l => l.code === value)?.name ?? value;

  const handleListboxKeys = (e: React.KeyboardEvent) => {
    if (e.key === 'Escape' && open) {
      e.stopPropagation();
      closeAndRefocus();
      return;
    }
    if (!open || (e.key !== 'ArrowDown' && e.key !== 'ArrowUp')) return;
    e.preventDefault();
    const options = Array.from(
      ref.current?.querySelectorAll<HTMLButtonElement>('[role="option"]') ?? []
    );
    if (options.length === 0) return;
    const idx = options.indexOf(document.activeElement as HTMLButtonElement);
    const next = e.key === 'ArrowDown'
      ? options[Math.min(options.length - 1, idx + 1)]
      : options[Math.max(0, idx - 1)];
    // from the search input, ArrowDown goes to the first option
    (idx === -1 && document.activeElement === inputRef.current
      ? options[e.key === 'ArrowDown' ? 0 : options.length - 1]
      : next
    ).focus();
  };

  return (
    <div
      ref={ref}
      className="relative text-left"
      onKeyDown={handleListboxKeys}
    >
      <button
        ref={triggerRef}
        type="button"
        onClick={() => setOpen(!open)}
        aria-haspopup="listbox"
        aria-expanded={open}
        aria-label={ariaLabel}
        className={cn(
          'w-full py-2.5 px-3.5 bg-brand-muted/60 dark:bg-white/5 rounded-xl border text-xs font-bold uppercase tracking-wider text-brand-dark dark:text-white flex items-center justify-between hover:border-brand-accent/50 transition-all select-none cursor-pointer',
          open ? 'border-brand-accent/50' : 'border-brand-accent/20 dark:border-white/10'
        )}
      >
        <span className="truncate normal-case">{label || placeholder}</span>
        <ChevronDown className={cn('size-3.5 shrink-0 text-brand-goldink dark:text-brand-accent transition-transform ms-2', open && 'rotate-180')} />
      </button>
      {open && (
        <div
          role="listbox"
          aria-label={ariaLabel}
          className="absolute top-[102%] right-0 left-0 bg-white dark:bg-[#1a1a1a] border border-black/10 dark:border-white/10 rounded-xl shadow-2xl p-2 z-50 animate-fade-in"
        >
          <div className="border-b border-black/5 dark:border-white/5 px-2 py-1.5">
            <input
              ref={inputRef}
              type="text"
              value={query}
              onChange={e => setQuery(e.target.value)}
              placeholder={t('langSelector.search')}
              aria-label={t('langSelector.search')}
              className="w-full bg-transparent px-1 py-1 text-xs outline-none placeholder:text-brand-dark/30 dark:placeholder:text-white/30 text-brand-dark dark:text-white"
            />
          </div>
          <div className="max-h-52 overflow-y-auto p-1 mt-1 space-y-0.5">
            {filtered.length === 0 && (
              <div className="px-3 py-3 text-center text-xs text-brand-dark/40 dark:text-white/40">{t('langSelector.noResults')}</div>
            )}
            {filtered.map(lang => (
              <button
                key={lang.code}
                type="button"
                role="option"
                aria-selected={value === lang.code}
                onClick={() => { onChange(lang.code); closeAndRefocus(); }}
                className={cn(
                  'flex w-full items-center justify-between rounded-lg px-2.5 py-2 text-xs font-bold uppercase tracking-wider transition-colors cursor-pointer',
                  value === lang.code
                    ? 'bg-brand-accent/10 text-brand-goldink dark:text-brand-accent'
                    : 'text-brand-dark/70 dark:text-white/70 hover:bg-brand-muted dark:hover:bg-white/5'
                )}
              >
                <span className="truncate">{lang.name}</span>
                {value === lang.code && <Check className="size-3.5 text-brand-goldink dark:text-brand-accent shrink-0" />}
              </button>
            ))}
          </div>
        </div>
      )}
    </div>
  );
}

/* ── Main component ─────────────────────────────────────────────── */
export default function LanguageSelector({
  sourceLang, targetLang, languages, isLoading, error,
  onSourceChange, onTargetChange,
}: LanguageSelectorProps) {
  const { t } = useI18n();

  if (error) {
    return (
      <div className="flex items-center gap-2 rounded-lg bg-destructive/10 px-3 py-2 text-xs text-destructive">
        <AlertCircle className="size-3.5 shrink-0" />
        <span>{t('dashboard.translate.language.loadErrorPrefix')} {error}</span>
      </div>
    );
  }

  if (isLoading) {
    return (
      <div className="flex items-center justify-center gap-2 py-2 text-muted-foreground">
        <Loader2 className="size-4 animate-spin" />
        <span className="text-xs">{t('dashboard.translate.language.loading')}</span>
      </div>
    );
  }

  const canSwap = sourceLang !== 'auto';

  return (
    <div className="grid grid-cols-11 gap-2 items-center">
      {/* Source */}
      <div className="col-span-5 relative text-left">
        <span className="text-[10px] font-bold text-brand-dark/40 dark:text-white/40 uppercase tracking-widest block mb-1">{t('langSelector.source')}</span>
        <Combobox
          value={sourceLang}
          options={languages}
          includeAuto
          autoLabel={t('dashboard.translate.language.autoDetect') || 'Auto-détecté'}
          placeholder={t('dashboard.translate.language.selectPlaceholder') || 'Langue...'}
          onChange={onSourceChange}
          ariaLabel={`${t('langSelector.source')} — ${t('dashboard.translate.language.autoDetect') || 'Auto-détecté'}`}
        />
      </div>

      {/* Swap Button */}
      <div className="col-span-1 flex justify-center pt-3 text-brand-dark/30 dark:text-white/30">
        <button
          type="button"
          onClick={() => canSwap && (() => { const s = sourceLang; onSourceChange(targetLang); onTargetChange(s); })()}
          disabled={!canSwap}
          aria-label={t('langSelector.swap')}
          className={cn(
            'flex size-7 items-center justify-center rounded-xl transition-all cursor-pointer',
            canSwap
              ? 'text-brand-dark/50 dark:text-white/50 hover:text-brand-goldink dark:text-brand-accent hover:bg-brand-muted/50 dark:hover:bg-white/5'
              : 'cursor-not-allowed opacity-30'
          )}
          title={t('langSelector.swap')}
        >
          <ArrowRightLeft size={12} />
        </button>
      </div>

      {/* Target */}
      <div className="col-span-5 relative text-left">
        <span className="text-[10px] font-bold text-brand-dark/40 dark:text-white/40 uppercase tracking-widest block mb-1">{t('langSelector.target')}</span>
        <Combobox
          value={targetLang}
          options={languages}
          includeAuto={false}
          autoLabel=""
          placeholder={t('dashboard.translate.language.selectPlaceholder') || 'Langue...'}
          onChange={onTargetChange}
          ariaLabel={t('langSelector.target')}
        />
      </div>
    </div>
  );
}
