import { useCallback, useEffect, useMemo, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import { Search } from 'lucide-react';
import { useAuthStore } from '@/store/authStore';
import { NAV_GROUPS, filterNavGroupsByRole, canAccessRoute } from '@/config/adminAccess';
import {
    Dialog,
    DialogContent,
    DialogTitle,
} from '@/components/ui/dialog';
import { Input } from '@/components/ui/input';
import { cn } from '@/lib/utils';

type PaletteItem = {
    id: string;
    label: string;
    group: string;
    path: string;
};

interface CommandPaletteProps {
    open: boolean;
    onOpenChange: (open: boolean) => void;
}

/** Looks like EventHub entity ids (base64url-ish). */
const ENTITY_ID_RE = /^[A-Za-z0-9_-]{16,40}$/;

export function CommandPalette({ open, onOpenChange }: CommandPaletteProps) {
    const { t } = useTranslation();
    const navigate = useNavigate();
    const role = useAuthStore((s) => s.user?.role);
    const [query, setQuery] = useState('');
    const [activeIndex, setActiveIndex] = useState(0);

    const items = useMemo<PaletteItem[]>(() => {
        const groups = filterNavGroupsByRole(NAV_GROUPS, role);
        const routes = groups.flatMap((g) =>
            g.items.map((item) => ({
                id: item.key,
                label: t(item.label),
                group: t(g.label),
                path: item.key,
            }))
        );
        routes.push(
            { id: '/profile', label: t('nav.profile'), group: t('navGroup.account'), path: '/profile' },
            { id: '/dashboard', label: t('nav.dashboard'), group: t('navGroup.overview'), path: '/dashboard' }
        );
        const seen = new Set<string>();
        return routes.filter((r) => {
            if (seen.has(r.path)) return false;
            seen.add(r.path);
            return true;
        });
    }, [role, t]);

    const filtered = useMemo(() => {
        const q = query.trim();
        const qLower = q.toLowerCase();
        const navHits = !qLower
            ? items
            : items.filter(
                  (item) =>
                      item.label.toLowerCase().includes(qLower) ||
                      item.group.toLowerCase().includes(qLower) ||
                      item.path.toLowerCase().includes(qLower)
              );

        if (!ENTITY_ID_RE.test(q)) return navHits;

        const jumps: PaletteItem[] = [];
        const pushIf = (path: string, labelKey: string, id: string) => {
            if (canAccessRoute(path.split('?')[0], role)) {
                jumps.push({
                    id,
                    label: `${t(labelKey)} · ${q}`,
                    group: t('layout.paletteJumpGroup'),
                    path,
                });
            }
        };
        pushIf(`/inbox/reports?selected=${encodeURIComponent(q)}`, 'layout.paletteOpenReportInbox', `jump-report-inbox-${q}`);
        pushIf(`/reports/${encodeURIComponent(q)}`, 'layout.paletteOpenReport', `jump-report-${q}`);
        pushIf(`/inbox/tickets?selected=${encodeURIComponent(q)}`, 'layout.paletteOpenTicketInbox', `jump-ticket-inbox-${q}`);
        pushIf(`/tickets/${encodeURIComponent(q)}`, 'layout.paletteOpenTicket', `jump-ticket-${q}`);
        pushIf(`/events/${encodeURIComponent(q)}`, 'layout.paletteOpenEvent', `jump-event-${q}`);
        pushIf(`/users/${encodeURIComponent(q)}`, 'layout.paletteOpenUser', `jump-user-${q}`);
        return [...jumps, ...navHits];
    }, [items, query, role, t]);

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

    useEffect(() => {
        if (!open) setQuery('');
    }, [open]);

    const go = useCallback(
        (path: string) => {
            onOpenChange(false);
            navigate(path);
        },
        [navigate, onOpenChange]
    );

    const onKeyDown = (e: React.KeyboardEvent) => {
        if (e.key === 'ArrowDown') {
            e.preventDefault();
            setActiveIndex((i) => Math.min(i + 1, Math.max(filtered.length - 1, 0)));
        } else if (e.key === 'ArrowUp') {
            e.preventDefault();
            setActiveIndex((i) => Math.max(i - 1, 0));
        } else if (e.key === 'Enter' && filtered[activeIndex]) {
            e.preventDefault();
            go(filtered[activeIndex].path);
        }
    };

    return (
        <Dialog open={open} onOpenChange={onOpenChange}>
            <DialogContent
                data-testid="command-palette"
                className="gap-0 overflow-hidden p-0 sm:max-w-lg"
                aria-describedby={undefined}
            >
                <DialogTitle className="sr-only">{t('layout.paletteTitle')}</DialogTitle>
                <div className="flex items-center border-b px-3">
                    <Search className="mr-2 h-4 w-4 shrink-0 text-muted-foreground" />
                    <Input
                        data-testid="palette-input"
                        autoFocus
                        value={query}
                        onChange={(e) => setQuery(e.target.value)}
                        onKeyDown={onKeyDown}
                        placeholder={t('layout.palettePlaceholder')}
                        className="h-12 border-0 shadow-none focus-visible:ring-0"
                    />
                </div>
                <ul className="max-h-72 overflow-auto py-2" role="listbox">
                    {filtered.length === 0 ? (
                        <li className="px-4 py-6 text-center text-sm text-muted-foreground">
                            {t('common.nothingFound')}
                        </li>
                    ) : (
                        filtered.map((item, index) => (
                            <li key={item.id}>
                                <button
                                    type="button"
                                    role="option"
                                    aria-selected={index === activeIndex}
                                    className={cn(
                                        'flex w-full items-center justify-between px-4 py-2 text-left text-sm',
                                        index === activeIndex ? 'bg-accent' : 'hover:bg-muted/60'
                                    )}
                                    onMouseEnter={() => setActiveIndex(index)}
                                    onClick={() => go(item.path)}
                                >
                                    <span className="font-medium">{item.label}</span>
                                    <span className="text-xs text-muted-foreground">{item.group}</span>
                                </button>
                            </li>
                        ))
                    )}
                </ul>
                <div className="border-t px-3 py-2 text-[11px] text-muted-foreground">
                    {t('layout.paletteHints')}
                </div>
            </DialogContent>
        </Dialog>
    );
}
