import { useEffect, useRef, useState } from 'react';
import { useNavigate } from 'react-router';
import { faMagnifyingGlass, faUser, faCalendar } from '@fortawesome/pro-duotone-svg-icons';
import { faIcon } from '@/lib/icon-wrapper';
import { Input } from '@/components/base/input/input';
import { Badge } from '@/components/base/badges/badges';
import { apiClient } from '@/lib/api-client';
import { formatShortDate } from '@/lib/format';
import { cx } from '@/utils/cx';

const SearchIcon = faIcon(faMagnifyingGlass);
const UserIcon = faIcon(faUser);
const CalendarIcon = faIcon(faCalendar);

type SearchResultType = 'lead' | 'patient' | 'appointment';

type SearchResult = {
    id: string;
    type: SearchResultType;
    title: string;
    subtitle: string;
    phone?: string;
};

type GlobalSearchProps = {
    onSelectResult?: (result: SearchResult) => void;
};

const TYPE_ICONS: Record<SearchResultType, ReturnType<typeof faIcon>> = {
    lead: UserIcon,
    patient: UserIcon,
    appointment: CalendarIcon,
};

const TYPE_BADGE_COLORS: Record<SearchResultType, 'brand' | 'success' | 'blue'> = {
    lead: 'brand',
    patient: 'success',
    appointment: 'blue',
};

const TYPE_LABELS: Record<SearchResultType, string> = {
    lead: 'Lead',
    patient: 'Patient',
    appointment: 'Appointment',
};

export const GlobalSearch = ({ onSelectResult }: GlobalSearchProps) => {
    const [query, setQuery] = useState('');
    const [results, setResults] = useState<SearchResult[]>([]);
    const [isOpen, setIsOpen] = useState(false);
    const [isSearching, setIsSearching] = useState(false);
    const [highlightedIndex, setHighlightedIndex] = useState(-1);
    const containerRef = useRef<HTMLDivElement>(null);
    const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);
    const navigate = useNavigate();

    useEffect(() => {
        if (debounceRef.current) clearTimeout(debounceRef.current);

        if (query.trim().length < 2) {
            setResults([]);
            setIsOpen(false);
            setIsSearching(false);
            return;
        }

        setIsSearching(true);
        debounceRef.current = setTimeout(async () => {
            try {
                const data = await apiClient.get<{
                    leads: Array<any>;
                    patients: Array<any>;
                    appointments: Array<any>;
                }>(`/api/search?q=${encodeURIComponent(query)}`, { silent: true });

                const searchResults: SearchResult[] = [];

                for (const l of data.leads ?? []) {
                    const name = l.contactName ? `${l.contactName.firstName} ${l.contactName.lastName}`.trim() : l.name;
                    searchResults.push({
                        id: l.id,
                        type: 'lead',
                        title: name || 'Unknown',
                        subtitle: [l.contactPhone?.primaryPhoneNumber, l.source, l.interestedService].filter(Boolean).join(' · '),
                        phone: l.contactPhone?.primaryPhoneNumber,
                    });
                }

                for (const p of data.patients ?? []) {
                    const name = p.fullName ? `${p.fullName.firstName} ${p.fullName.lastName}`.trim() : p.name;
                    searchResults.push({
                        id: p.id,
                        type: 'patient',
                        title: name || 'Unknown',
                        subtitle: p.phones?.primaryPhoneNumber ?? '',
                        phone: p.phones?.primaryPhoneNumber,
                    });
                }

                for (const a of data.appointments ?? []) {
                    const date = a.scheduledAt ? formatShortDate(a.scheduledAt) : '';
                    searchResults.push({
                        id: a.id,
                        type: 'appointment',
                        title: a.doctorName ?? 'Appointment',
                        subtitle: [a.department, date, a.status].filter(Boolean).join(' · '),
                    });
                }

                setResults(searchResults);
                setIsOpen(true);
            } catch {
                setResults([]);
            } finally {
                setIsSearching(false);
                setHighlightedIndex(-1);
            }
        }, 300);

        return () => { if (debounceRef.current) clearTimeout(debounceRef.current); };
    }, [query]);

    // Close on outside click
    useEffect(() => {
        const handleClickOutside = (event: MouseEvent) => {
            if (containerRef.current && !containerRef.current.contains(event.target as Node)) {
                setIsOpen(false);
            }
        };
        document.addEventListener('mousedown', handleClickOutside);
        return () => document.removeEventListener('mousedown', handleClickOutside);
    }, []);

    const handleSelect = (result: SearchResult) => {
        setIsOpen(false);
        setQuery('');
        if (onSelectResult) {
            onSelectResult(result);
        } else {
            navigate(`/patient/${result.id}`);
        }
    };

    const handleKeyDown = (event: React.KeyboardEvent) => {
        if (!isOpen || results.length === 0) return;

        if (event.key === 'ArrowDown') {
            event.preventDefault();
            setHighlightedIndex((prev) => (prev < results.length - 1 ? prev + 1 : 0));
        } else if (event.key === 'ArrowUp') {
            event.preventDefault();
            setHighlightedIndex((prev) => (prev > 0 ? prev - 1 : results.length - 1));
        } else if (event.key === 'Enter' && highlightedIndex >= 0) {
            event.preventDefault();
            handleSelect(results[highlightedIndex]);
        } else if (event.key === 'Escape') {
            setIsOpen(false);
        }
    };

    // Group results by type
    const groupedResults: Record<string, SearchResult[]> = {};
    for (const result of results) {
        const groupLabel = `${TYPE_LABELS[result.type]}s`;
        if (!groupedResults[groupLabel]) {
            groupedResults[groupLabel] = [];
        }
        groupedResults[groupLabel].push(result);
    }

    let flatIndex = -1;

    return (
        <div ref={containerRef} className="relative w-64" onKeyDown={handleKeyDown}>
            <Input
                placeholder="Search patients, leads, appointments..."
                icon={SearchIcon}
                aria-label="Global search"
                value={query}
                onChange={(value) => setQuery(value)}
                onFocus={() => {
                    if (results.length > 0) setIsOpen(true);
                }}
                shortcut="/"
            />

            {isOpen && (
                <div className="absolute top-full right-0 left-0 z-50 mt-1 overflow-hidden rounded-xl border border-secondary bg-primary shadow-lg">
                    {isSearching && (
                        <div className="flex items-center justify-center px-4 py-6">
                            <svg
                                fill="none"
                                viewBox="0 0 20 20"
                                className="size-5 animate-spin text-fg-brand-primary"
                            >
                                <circle
                                    className="stroke-current opacity-30"
                                    cx="10"
                                    cy="10"
                                    r="8"
                                    fill="none"
                                    strokeWidth="2"
                                />
                                <circle
                                    className="origin-center stroke-current"
                                    cx="10"
                                    cy="10"
                                    r="8"
                                    fill="none"
                                    strokeWidth="2"
                                    strokeDasharray="12.5 50"
                                    strokeLinecap="round"
                                />
                            </svg>
                        </div>
                    )}

                    {!isSearching && results.length === 0 && (
                        <div className="flex flex-col items-center gap-1 px-4 py-6 text-center">
                            <SearchIcon className="size-5 text-fg-quaternary" />
                            <p className="text-sm font-medium text-secondary">No results</p>
                            <p className="text-xs text-tertiary">Try a different search term</p>
                        </div>
                    )}

                    {!isSearching &&
                        results.length > 0 &&
                        Object.entries(groupedResults).map(([groupLabel, groupResults]) => (
                            <div key={groupLabel}>
                                <div className="px-4 py-2 text-xs font-bold uppercase text-quaternary">
                                    {groupLabel}
                                </div>
                                {groupResults.map((result) => {
                                    flatIndex++;
                                    const currentIndex = flatIndex;
                                    const Icon = TYPE_ICONS[result.type];

                                    return (
                                        <button
                                            key={result.id}
                                            type="button"
                                            className={cx(
                                                'flex w-full cursor-pointer items-center gap-3 px-4 py-2.5 text-left transition duration-100 ease-linear',
                                                currentIndex === highlightedIndex
                                                    ? 'bg-active'
                                                    : 'hover:bg-primary_hover',
                                            )}
                                            onClick={() => handleSelect(result)}
                                            onMouseEnter={() => setHighlightedIndex(currentIndex)}
                                        >
                                            <div className="flex size-8 shrink-0 items-center justify-center rounded-full bg-secondary">
                                                <Icon className="size-4 text-fg-quaternary" />
                                            </div>
                                            <div className="flex min-w-0 flex-1 flex-col">
                                                <span className="truncate text-sm font-semibold text-primary">
                                                    {result.title}
                                                </span>
                                                <span className="truncate text-xs text-tertiary">
                                                    {result.subtitle}
                                                </span>
                                            </div>
                                            <Badge size="sm" type="pill-color" color={TYPE_BADGE_COLORS[result.type]}>
                                                {TYPE_LABELS[result.type]}
                                            </Badge>
                                        </button>
                                    );
                                })}
                            </div>
                        ))}
                </div>
            )}
        </div>
    );
};
