// @design-system: overlays/CommandPalette
// Registered at /design-system#commandpalette-overlay

'use client';

/**
 * CommandPalette - global ⌘K / Ctrl+K search overlay.
 *
 * Built on cmdk + Radix Dialog. Provides quick navigation to pages,
 * deal search, and common actions from anywhere in the app.
 *
 * Keyboard: ⌘K / Ctrl+K to open, Escape to close, arrows to navigate, Enter to select.
 */

import { useState, useEffect, useCallback, useMemo } from 'react';
import { Command } from 'cmdk';
import * as RadixDialog from '@radix-ui/react-dialog';
import * as RadixVisuallyHidden from '@radix-ui/react-visually-hidden';
import { cn } from '@/lib/cn';
import { dirForLocale } from '@/lib/i18n';
import { useT, useLocale } from '@/lib/i18n/react';
import { Icon, type IconName } from '@/components/ui/icons/Icon';
import { useSearchSuggest } from '@/features/search/useSearchSuggest';
import { useAuthHint } from '@/lib/hooks/useAuthHint';
import type { StringBundle } from '@/lib/i18n/types';
import { buildDealsPath } from '@/lib/url/buildDealsPath';

// ─── Navigation items ──────────────────────────────────────────────────────

type CommandPaletteKey = keyof StringBundle['command_palette'];

interface NavItem {
  id: string;
  /** i18n key in 'command_palette' namespace */
  labelKey: CommandPaletteKey;
  icon: IconName;
  href: string;
  groupKey: 'group_pages' | 'group_admin';
  adminOnly?: boolean;
  /** Extra search keywords (not displayed) */
  keywords?: string[];
}

const NAV_ITEMS: NavItem[] = [
  {
    id: 'home',
    labelKey: 'nav_home',
    icon: 'Check',
    href: '/',
    groupKey: 'group_pages',
    keywords: ['feed', 'main'],
  },
  {
    id: 'search',
    labelKey: 'nav_search',
    icon: 'Search',
    href: '/search',
    groupKey: 'group_pages',
    keywords: ['find', 'deals'],
  },
  {
    id: 'purchases',
    labelKey: 'nav_purchases',
    icon: 'ShoppingBag',
    href: '/purchases',
    groupKey: 'group_pages',
    keywords: ['orders', 'history'],
  },
  {
    id: 'profile',
    labelKey: 'nav_profile',
    icon: 'User',
    href: '/profile',
    groupKey: 'group_pages',
    keywords: ['account', 'settings'],
  },
  {
    id: 'settings',
    labelKey: 'nav_settings',
    icon: 'Settings',
    href: '/settings',
    groupKey: 'group_pages',
  },
  {
    id: 'club',
    labelKey: 'nav_club',
    icon: 'Heart',
    href: '/club',
    groupKey: 'group_pages',
    keywords: ['club', 'member'],
  },
  {
    id: 'faq',
    labelKey: 'nav_faq',
    icon: 'AlertCircle',
    href: '/faq',
    groupKey: 'group_pages',
    keywords: ['help', 'questions'],
  },
  { id: 'about', labelKey: 'nav_about', icon: 'Info', href: '/about', groupKey: 'group_pages' },
  {
    id: 'accessibility',
    labelKey: 'nav_accessibility',
    icon: 'Eye',
    href: '/accessibility',
    groupKey: 'group_pages',
    keywords: ['a11y'],
  },
  {
    id: 'admin-dashboard',
    labelKey: 'nav_admin_dashboard',
    icon: 'LayoutGrid',
    href: '/admin',
    groupKey: 'group_admin',
    adminOnly: true,
    keywords: ['admin', 'dashboard'],
  },
  {
    id: 'admin-users',
    labelKey: 'nav_admin_users',
    icon: 'User',
    href: '/admin/users',
    groupKey: 'group_admin',
    adminOnly: true,
    keywords: ['admin', 'users'],
  },
  {
    id: 'admin-deals',
    labelKey: 'nav_admin_deals',
    icon: 'Star',
    href: '/admin/deals',
    groupKey: 'group_admin',
    adminOnly: true,
    keywords: ['admin', 'deals'],
  },
  {
    id: 'admin-reports',
    labelKey: 'nav_admin_reports',
    icon: 'AlertCircle',
    href: '/admin/reports',
    groupKey: 'group_admin',
    adminOnly: true,
    keywords: ['admin', 'reports'],
  },
];

const LOCALIZED_EXACT_PATHS = new Set([
  '/',
  '/near-you',
  '/whats-left',
  '/deals',
  '/refer',
  '/affiliate',
  '/affiliate-program',
]);
const LOCALIZED_PATH_PREFIXES = ['/deals/', '/categories/'];

export function localizeCommandPath(path: string, locale: 'he' | 'en'): string {
  if (locale === 'he' || path.startsWith('/en/')) return path;
  const isLocalizedRoute =
    LOCALIZED_EXACT_PATHS.has(path) ||
    LOCALIZED_PATH_PREFIXES.some((prefix) => path.startsWith(prefix));
  return isLocalizedRoute ? (path === '/' ? '/en/' : `/en${path}`) : path;
}

// ─── Props ──────────────────────────────────────────────────────────────────

export interface CommandPaletteProps {
  /** Controlled open state. If omitted, manages its own state via ⌘K. */
  open?: boolean;
  /** Callback when open state changes. */
  onOpenChange?: (open: boolean) => void;
  className?: string;
}

// ─── Component ──────────────────────────────────────────────────────────────

export function CommandPalette({
  open: controlledOpen,
  onOpenChange,
  className,
}: CommandPaletteProps) {
  const t = useT('command_palette');
  const { locale } = useLocale();
  const dir = dirForLocale(locale);
  const { isAdmin } = useAuthHint();
  const [internalOpen, setInternalOpen] = useState(false);
  const [search, setSearch] = useState('');

  const isOpen = controlledOpen ?? internalOpen;
  const setOpen = useCallback(
    (next: boolean) => {
      setInternalOpen(next);
      if (!next) {
        setSearch('');
      }
      onOpenChange?.(next);
    },
    [onOpenChange],
  );

  // ── Global keyboard shortcut ────────────────────────────────────────────
  useEffect(() => {
    if (controlledOpen !== undefined) return;

    function onKeyDown(e: KeyboardEvent) {
      if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === 'k') {
        e.preventDefault();
        setOpen(!isOpen);
      }
    }
    document.addEventListener('keydown', onKeyDown);
    return () => document.removeEventListener('keydown', onKeyDown);
  }, [controlledOpen, isOpen, setOpen]);

  const { suggestions, loading: suggestLoading } = useSearchSuggest(search, locale);
  const showLoading = search.trim() ? suggestLoading : false;
  const visibleNavItems = useMemo(
    () => NAV_ITEMS.filter((item) => !item.adminOnly || isAdmin),
    [isAdmin],
  );
  const pageItems = visibleNavItems.filter((item) => item.groupKey === 'group_pages');
  const adminItems = visibleNavItems.filter((item) => item.groupKey === 'group_admin');

  function navigate(href: string) {
    setOpen(false);
    window.location.assign(href);
  }

  return (
    <RadixDialog.Root open={isOpen} onOpenChange={setOpen}>
      <RadixDialog.Portal>
        <RadixDialog.Overlay
          data-testid="command-palette-overlay"
          className={cn(
            'z-overlay bg-surface-overlay fixed inset-0',
            'data-[state=open]:animate-in data-[state=open]:fade-in-0',
            'data-[state=closed]:animate-out data-[state=closed]:fade-out-0',
            'motion-reduce:transition-none',
          )}
        />
        <RadixDialog.Content
          data-testid="command-palette-content"
          dir={dir}
          className={cn(
            'z-modal fixed top-[20%] left-1/2',
            '-translate-x-1/2',
            'w-[calc(100%-2rem)] max-w-lg',
            'border-border-default bg-surface-base rounded-xl border',
            'shadow-xl',
            'focus:outline-none',
            'data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:slide-in-from-top-2',
            'data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-top-2',
            'motion-reduce:animate-none motion-reduce:transition-none',
            className,
          )}
        >
          <RadixVisuallyHidden.Root>
            <RadixDialog.Title>{t('title')}</RadixDialog.Title>
          </RadixVisuallyHidden.Root>

          <Command
            label={t('title')}
            loop
            dir={dir}
            data-testid="command-palette"
            className="flex flex-col"
          >
            {/* Input */}
            <div className="border-border-default flex items-center gap-2 border-b px-4 py-3">
              <Icon name="Search" size="sm" color="muted" />
              <Command.Input
                data-testid="command-palette-input"
                value={search}
                onValueChange={setSearch}
                placeholder={t('placeholder')}
                dir={dir}
                aria-busy={showLoading || undefined}
                className={cn(
                  'text-text-primary flex-1 bg-transparent text-start text-sm',
                  'placeholder:text-text-muted',
                  'focus-visible:ring-brand-primary-500 focus-visible:ring-2 focus-visible:outline-none',
                )}
              />
              <kbd
                className={cn(
                  'border-border-default hidden rounded-md border',
                  'bg-surface-raised text-text-muted px-1.5 py-0.5 text-xs',
                  'sm:inline-block',
                )}
              >
                {t('shortcut')}
              </kbd>
            </div>

            {/* List */}
            <Command.List
              data-testid="command-palette-list"
              className={cn('max-h-72 overflow-y-auto overscroll-contain', 'p-2')}
            >
              <Command.Empty className="text-text-muted py-6 text-center text-sm">
                {t('no_results')}
              </Command.Empty>

              {showLoading && (
                <div
                  data-testid="command-palette-loading"
                  role="status"
                  aria-live="polite"
                  className="text-text-muted px-3 py-2 text-sm"
                >
                  {t('searching')}
                </div>
              )}

              {/* Navigation group */}
              <Command.Group
                heading={t('group_pages')}
                className="[&_[cmdk-group-heading]]:text-text-muted [&_[cmdk-group-heading]]:mb-1 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium"
              >
                {pageItems.map((item) => (
                  <Command.Item
                    key={item.id}
                    value={t(item.labelKey)}
                    keywords={item.keywords}
                    onSelect={() => navigate(localizeCommandPath(item.href, locale))}
                    data-testid={`command-palette-item-${item.id}`}
                    className={cn(
                      'flex cursor-pointer items-center gap-3 rounded-lg px-3 py-2.5 text-start text-sm',
                      'text-text-primary',
                      'data-[selected=true]:bg-brand-primary-50 data-[selected=true]:text-brand-primary-700',
                      'transition-colors',
                    )}
                  >
                    <Icon name={item.icon} size="sm" />
                    <span>{t(item.labelKey)}</span>
                  </Command.Item>
                ))}
              </Command.Group>

              {adminItems.length > 0 && (
                <Command.Group
                  heading={t('group_admin')}
                  className="[&_[cmdk-group-heading]]:text-text-muted [&_[cmdk-group-heading]]:mb-1 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:pt-2 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium"
                >
                  {adminItems.map((item) => (
                    <Command.Item
                      key={item.id}
                      value={t(item.labelKey)}
                      keywords={item.keywords}
                      onSelect={() => navigate(localizeCommandPath(item.href, locale))}
                      data-testid={`command-palette-item-${item.id}`}
                      className={cn(
                        'flex cursor-pointer items-center gap-3 rounded-lg px-3 py-2.5 text-start text-sm',
                        'text-text-primary',
                        'data-[selected=true]:bg-brand-primary-50 data-[selected=true]:text-brand-primary-700',
                        'transition-colors',
                      )}
                    >
                      <Icon name={item.icon} size="sm" />
                      <span>{t(item.labelKey)}</span>
                    </Command.Item>
                  ))}
                </Command.Group>
              )}

              {/* Deal suggestions */}
              {suggestions?.deals && suggestions.deals.length > 0 && (
                <Command.Group
                  heading={t('group_deals')}
                  className="[&_[cmdk-group-heading]]:text-text-muted [&_[cmdk-group-heading]]:mb-1 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:pt-2 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium"
                >
                  {suggestions.deals.map((deal) => (
                    <Command.Item
                      key={deal.id}
                      value={`deal-${deal.id}-${deal.title}`}
                      onSelect={() =>
                        navigate(buildDealsPath({ locale, catSlug: deal.slug ?? undefined }))
                      }
                      data-testid={`command-palette-item-deal-${deal.id}`}
                      className={cn(
                        'flex cursor-pointer items-center gap-3 rounded-lg px-3 py-2.5 text-start text-sm',
                        'text-text-primary',
                        'data-[selected=true]:bg-brand-primary-50 data-[selected=true]:text-brand-primary-700',
                        'transition-colors',
                      )}
                    >
                      <Icon name="Star" size="sm" />
                      <div className="flex min-w-0 flex-1 flex-col">
                        <span className="truncate font-medium">{deal.title}</span>
                        {deal.vendorName && (
                          <span className="text-text-muted truncate text-xs">
                            {deal.vendorName}
                          </span>
                        )}
                      </div>
                    </Command.Item>
                  ))}
                </Command.Group>
              )}

              {/* Category suggestions */}
              {suggestions?.categories && suggestions.categories.length > 0 && (
                <Command.Group
                  heading={t('group_categories')}
                  className="[&_[cmdk-group-heading]]:text-text-muted [&_[cmdk-group-heading]]:mb-1 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:pt-2 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium"
                >
                  {suggestions.categories.map((cat) => (
                    <Command.Item
                      key={`cat-${cat.slug}`}
                      value={`cat-${cat.slug}-${cat.name}`}
                      onSelect={() => navigate(buildDealsPath({ locale, catSlug: cat.slug }))}
                      data-testid={`command-palette-item-category-${cat.slug}`}
                      className={cn(
                        'flex cursor-pointer items-center gap-3 rounded-lg px-3 py-2.5 text-start text-sm',
                        'text-text-primary',
                        'data-[selected=true]:bg-brand-primary-50 data-[selected=true]:text-brand-primary-700',
                        'transition-colors',
                      )}
                    >
                      <Icon name="LayoutGrid" size="sm" />
                      <span className="truncate">{cat.name}</span>
                    </Command.Item>
                  ))}
                </Command.Group>
              )}

              {/* Tag suggestions */}
              {suggestions?.tags && suggestions.tags.length > 0 && (
                <Command.Group
                  heading={t('group_tags')}
                  className="[&_[cmdk-group-heading]]:text-text-muted [&_[cmdk-group-heading]]:mb-1 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:pt-2 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium"
                >
                  {suggestions.tags.map((tag) => (
                    <Command.Item
                      key={`tag-${tag.slug}`}
                      value={`tag-${tag.slug}-${tag.name}`}
                      onSelect={() => navigate(localizeCommandPath(`/tag/${tag.slug}`, locale))}
                      data-testid={`command-palette-item-tag-${tag.slug}`}
                      className={cn(
                        'flex cursor-pointer items-center gap-3 rounded-lg px-3 py-2.5 text-start text-sm',
                        'text-text-primary',
                        'data-[selected=true]:bg-brand-primary-50 data-[selected=true]:text-brand-primary-700',
                        'transition-colors',
                      )}
                    >
                      <Icon name="Bookmark" size="sm" />
                      <span className="truncate">{tag.name}</span>
                    </Command.Item>
                  ))}
                </Command.Group>
              )}

              {/* Vendor suggestions */}
              {suggestions?.vendors && suggestions.vendors.length > 0 && (
                <Command.Group
                  heading={t('group_businesses')}
                  className="[&_[cmdk-group-heading]]:text-text-muted [&_[cmdk-group-heading]]:mb-1 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:pt-2 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium"
                >
                  {suggestions.vendors.map((vendor) => (
                    <Command.Item
                      key={`vendor-${vendor.id}`}
                      value={`vendor-${vendor.id}-${vendor.displayName}`}
                      onSelect={() =>
                        navigate(localizeCommandPath(`/business/${vendor.id}`, locale))
                      }
                      data-testid={`command-palette-item-vendor-${vendor.id}`}
                      className={cn(
                        'flex cursor-pointer items-center gap-3 rounded-lg px-3 py-2.5 text-start text-sm',
                        'text-text-primary',
                        'data-[selected=true]:bg-brand-primary-50 data-[selected=true]:text-brand-primary-700',
                        'transition-colors',
                      )}
                    >
                      <Icon name="Store" size="sm" />
                      <div className="flex min-w-0 flex-1 flex-col">
                        <span className="truncate font-medium">{vendor.displayName}</span>
                        {vendor.city && (
                          <span className="text-text-muted truncate text-xs">{vendor.city}</span>
                        )}
                      </div>
                    </Command.Item>
                  ))}
                </Command.Group>
              )}
            </Command.List>

            {/* Footer */}
            <div className="border-border-default text-text-muted flex flex-wrap items-center justify-between gap-2 border-t px-4 py-2 text-xs">
              <div className="flex flex-wrap items-center gap-2">
                <span className="flex items-center gap-1">
                  <kbd className="border-border-default bg-surface-raised rounded border px-1 py-0.5">
                    ↑
                  </kbd>
                  <kbd className="border-border-default bg-surface-raised rounded border px-1 py-0.5">
                    ↓
                  </kbd>
                  {t('hint_navigate')}
                </span>
                <span className="flex items-center gap-1">
                  <kbd className="border-border-default bg-surface-raised rounded border px-1 py-0.5">
                    ↵
                  </kbd>
                  {t('hint_select')}
                </span>
              </div>
              <span className="flex items-center gap-1">
                <kbd className="border-border-default bg-surface-raised rounded border px-1 py-0.5">
                  esc
                </kbd>
                {t('hint_close')}
              </span>
            </div>
          </Command>
        </RadixDialog.Content>
      </RadixDialog.Portal>
    </RadixDialog.Root>
  );
}
