import { useState, useEffect, useCallback } from 'react';
import { router } from '@inertiajs/react';
import { useQuery } from '@tanstack/react-query';
import {
  CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList,
} from '@/components/ui/command';
import { Building2, GraduationCap, ShoppingCart, User, Users } from 'lucide-react';

type Course = { id: string; title: string; slug: string };
type Company = { id: string; name: string };
type Profile = { id: string; full_name: string | null; email: string };
type Order = { id: string; customer_name: string; customer_email: string; status: string };
type Trainer = { id: string; first_name: string; last_name: string };

const DEBOUNCE_MS = 250;

const fetchSearch = async <T,>(
  endpoint: string,
  q: string,
  signal?: AbortSignal,
): Promise<T[]> => {
  if (!q || q.length < 2) return [];
  const res = await fetch(`${endpoint}?q=${encodeURIComponent(q)}`, { signal });
  if (!res.ok) return [];
  return res.json();
};

const AdminCommandPalette = () => {
  const [open, setOpen] = useState(false);
  const [search, setSearch] = useState('');
  const [debouncedSearch, setDebouncedSearch] = useState('');

  // Debounce: only push the search into React Query's key once typing settles.
  // React Query auto-cancels in-flight requests when the queryKey changes, so
  // pairing this with the AbortSignal below stops the previous fetch the moment
  // a new one starts.
  useEffect(() => {
    const t = setTimeout(() => setDebouncedSearch(search), DEBOUNCE_MS);
    return () => clearTimeout(t);
  }, [search]);

  // Toggle palette with Cmd-K / Ctrl-K
  useEffect(() => {
    const down = (e: KeyboardEvent) => {
      if (e.key === 'k' && (e.metaKey || e.ctrlKey)) {
        e.preventDefault();
        setOpen((o) => !o);
      }
    };
    document.addEventListener('keydown', down);
    return () => document.removeEventListener('keydown', down);
  }, []);

  const enabled = open && debouncedSearch.length > 1;

  const { data: courses, isFetching: coursesLoading } = useQuery({
    queryKey: ['cmd-courses', debouncedSearch],
    queryFn: ({ signal }) => fetchSearch<Course>('/api/admin/search/courses', debouncedSearch, signal),
    enabled,
    staleTime: 30_000,
  });

  const { data: companies, isFetching: companiesLoading } = useQuery({
    queryKey: ['cmd-companies', debouncedSearch],
    queryFn: ({ signal }) => fetchSearch<Company>('/api/admin/search/companies', debouncedSearch, signal),
    enabled,
    staleTime: 30_000,
  });

  const { data: profiles, isFetching: profilesLoading } = useQuery({
    queryKey: ['cmd-profiles', debouncedSearch],
    queryFn: ({ signal }) => fetchSearch<Profile>('/api/admin/search/users', debouncedSearch, signal),
    enabled,
    staleTime: 30_000,
  });

  const { data: orders, isFetching: ordersLoading } = useQuery({
    queryKey: ['cmd-orders', debouncedSearch],
    queryFn: ({ signal }) => fetchSearch<Order>('/api/admin/search/orders', debouncedSearch, signal),
    enabled,
    staleTime: 30_000,
  });

  const { data: trainers, isFetching: trainersLoading } = useQuery({
    queryKey: ['cmd-trainers', debouncedSearch],
    queryFn: ({ signal }) => fetchSearch<Trainer>('/api/admin/search/trainers', debouncedSearch, signal),
    enabled,
    staleTime: 30_000,
  });

  const anyLoading =
    coursesLoading || companiesLoading || profilesLoading || ordersLoading || trainersLoading;

  // True when the user has typed but the debounced value hasn't caught up yet.
  const debouncing = enabled && search !== debouncedSearch;

  const go = useCallback((path: string) => {
    setOpen(false);
    setSearch('');
    setDebouncedSearch('');
    router.visit(path);
  }, []);

  return (
    <CommandDialog open={open} onOpenChange={setOpen} shouldFilter={false}>
      <CommandInput
        placeholder="Search courses, companies, bookings, people…"
        value={search}
        onValueChange={setSearch}
      />
      <CommandList>
        {/* While we're either debouncing or actively fetching, swallow the empty-state
            so the user doesn't see "No results found" flash before results land. */}
        {!debouncing && !anyLoading && <CommandEmpty>No results found.</CommandEmpty>}

        {!search && (
          <CommandGroup heading="Quick Navigation">
            <CommandItem onSelect={() => go('/admin')}>Dashboard</CommandItem>
            <CommandItem onSelect={() => go('/admin/orders')}>Bookings</CommandItem>
            <CommandItem onSelect={() => go('/admin/companies')}>Companies</CommandItem>
            <CommandItem onSelect={() => go('/admin/courses')}>Courses</CommandItem>
            <CommandItem onSelect={() => go('/admin/accounts')}>Individual Accounts</CommandItem>
            <CommandItem onSelect={() => go('/admin/trainers')}>Trainers</CommandItem>
            <CommandItem onSelect={() => go('/admin/calendar')}>Training Calendar</CommandItem>
            <CommandItem onSelect={() => go('/admin/discount-codes')}>Discount Codes</CommandItem>
          </CommandGroup>
        )}

        {(debouncing || anyLoading) && search.length > 1 && (
          <div className="px-3 py-6 text-center text-xs text-muted-foreground">
            Searching…
          </div>
        )}

        {courses && courses.length > 0 && (
          <CommandGroup heading="Courses">
            {courses.map((c) => (
              <CommandItem key={c.id} onSelect={() => go(`/admin/courses/${c.id}/edit`)}>
                <GraduationCap className="mr-2 h-4 w-4 text-muted-foreground" />
                {c.title}
              </CommandItem>
            ))}
          </CommandGroup>
        )}

        {companies && companies.length > 0 && (
          <CommandGroup heading="Companies">
            {companies.map((c) => (
              <CommandItem key={c.id} onSelect={() => go(`/admin/companies/${c.id}`)}>
                <Building2 className="mr-2 h-4 w-4 text-muted-foreground" />
                {c.name}
              </CommandItem>
            ))}
          </CommandGroup>
        )}

        {orders && orders.length > 0 && (
          <CommandGroup heading="Bookings">
            {orders.map((o) => (
              <CommandItem key={o.id} onSelect={() => go('/admin/orders')}>
                <ShoppingCart className="mr-2 h-4 w-4 text-muted-foreground" />
                {o.customer_name} — {o.status}
              </CommandItem>
            ))}
          </CommandGroup>
        )}

        {profiles && profiles.length > 0 && (
          <CommandGroup heading="People">
            {profiles.map((p) => (
              <CommandItem key={p.id} onSelect={() => go('/admin/accounts')}>
                <User className="mr-2 h-4 w-4 text-muted-foreground" />
                {p.full_name || p.email}
              </CommandItem>
            ))}
          </CommandGroup>
        )}

        {trainers && trainers.length > 0 && (
          <CommandGroup heading="Trainers">
            {trainers.map((t) => (
              <CommandItem key={t.id} onSelect={() => go('/admin/trainers')}>
                <Users className="mr-2 h-4 w-4 text-muted-foreground" />
                {t.first_name} {t.last_name}
              </CommandItem>
            ))}
          </CommandGroup>
        )}
      </CommandList>
    </CommandDialog>
  );
};

export default AdminCommandPalette;
