// @design-system: overlays/SearchAutocomplete
// Registered at /design-system#searchautocomplete-overlay

'use client';

/**
 * SearchAutocomplete — cmdk-powered autocomplete dropdown for search.
 *
 * Renders grouped suggestions (deals, categories, tags, vendors) fetched via
 * useSearchSuggest. Supports keyboard navigation, click-outside close, and
 * Enter-to-submit fallback for full-page search.
 *
 * RTL-first: all spacing uses logical props (ps-/pe-/ms-/me-/start-/end-).
 */

import { useRef, useCallback, useEffect, useState } from 'react';
import { Command } from 'cmdk';
import { cn } from '@/lib/cn';
import { useT } from '@/lib/i18n/react';
import { formatShekelFloat } from '@/lib/money';
import type { Locale } from '@/lib/i18n';
import { Icon } from '@/components/ui/icons/Icon';
import { Image } from '@/components/ui/primitives/Image';
import { Spinner } from '@/components/ui/feedback/Spinner';
import { useSearchSuggest } from '@/features/search/useSearchSuggest';
import type {
  DealSuggestion,
  EntitySuggestion,
  VendorSuggestion,
} from '@/features/search/SearchClient';

// ─── Types ───────────────────────────────────────────────────────────────────

export type SuggestionItem =
  | { type: 'deal'; deal: DealSuggestion }
  | { type: 'category'; entity: EntitySuggestion }
  | { type: 'tag'; entity: EntitySuggestion }
  | { type: 'vendor'; vendor: VendorSuggestion }
  | { type: 'search'; query: string };

export interface SearchAutocompleteProps {
  query: string;
  onQueryChange: (q: string) => void;
  onSelect: (item: SuggestionItem) => void;
  onSubmit: (q: string) => void;
  locale: Locale;
  placeholder?: string;
  className?: string;
}

// ─── Suggestion row sub-components ───────────────────────────────────────────

const ITEM_CLASS =
  'flex cursor-pointer items-center gap-3 rounded-lg px-3 py-2 text-sm text-text-primary data-[selected=true]:bg-brand-primary-50 data-[selected=true]:text-brand-primary-700 transition-colors';

interface DealSuggestionRowProps {
  deal: DealSuggestion;
  onSelect: () => void;
}

function DealSuggestionRow({ deal, onSelect }: DealSuggestionRowProps) {
  return (
    <Command.Item value={`deal-${deal.id}`} onSelect={onSelect} className={ITEM_CLASS}>
      {/* Thumbnail */}
      <span className="bg-surface-subtle relative flex size-8 shrink-0 items-center justify-center overflow-hidden rounded">
        {deal.imageSrc ? (
          <Image
            src={deal.imageSrc}
            alt=""
            decorative
            width={32}
            height={32}
            variant="thumb"
            className="size-8 object-cover"
          />
        ) : (
          <Icon name="ShoppingBag" size="sm" className="text-text-muted" aria-hidden />
        )}
      </span>

      {/* Text */}
      <span className="min-w-0 flex-1">
        <span className="block truncate font-medium">{deal.title}</span>
        <span className="text-text-muted block truncate text-xs">{deal.vendorName}</span>
      </span>

      {/* Price + discount */}
      <span className="flex shrink-0 flex-col items-end gap-0.5">
        <span className="text-text-primary text-sm font-semibold">
          {formatShekelFloat(deal.discountedPrice)}
        </span>
        <span className="bg-brand-primary-100 text-2xs text-brand-primary-700 rounded px-1 py-0.5 font-medium">
          -{deal.discountPercent}%
        </span>
      </span>
    </Command.Item>
  );
}

interface EntityRowProps {
  entity: EntitySuggestion;
  type: 'category' | 'tag';
  onSelect: () => void;
}

function EntityRow({ entity, type, onSelect }: EntityRowProps) {
  return (
    <Command.Item value={`${type}-${entity.slug}`} onSelect={onSelect} className={ITEM_CLASS}>
      <Icon
        name={type === 'category' ? 'LayoutGrid' : 'Bookmark'}
        size="sm"
        className="text-text-muted shrink-0"
        aria-hidden
      />
      <span className="truncate">{entity.name}</span>
    </Command.Item>
  );
}

interface VendorRowProps {
  vendor: VendorSuggestion;
  onSelect: () => void;
}

function VendorRow({ vendor, onSelect }: VendorRowProps) {
  return (
    <Command.Item value={`vendor-${vendor.id}`} onSelect={onSelect} className={ITEM_CLASS}>
      <span className="bg-surface-subtle relative flex size-6 shrink-0 items-center justify-center overflow-hidden rounded">
        {vendor.logoUrl ? (
          <Image
            src={vendor.logoUrl}
            alt=""
            decorative
            width={24}
            height={24}
            variant="thumb"
            className="size-6 object-cover"
          />
        ) : (
          <Icon name="Store" size="xs" className="text-text-muted" aria-hidden />
        )}
      </span>
      <span className="min-w-0 flex-1">
        <span className="block truncate">{vendor.displayName}</span>
        {vendor.city && (
          <span className="text-text-muted block truncate text-xs">{vendor.city}</span>
        )}
      </span>
    </Command.Item>
  );
}

// ─── Group heading style ──────────────────────────────────────────────────────

const GROUP_CLASS =
  '[&_[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';

// ─── Main component ───────────────────────────────────────────────────────────

export function SearchAutocomplete({
  query,
  onQueryChange,
  onSelect,
  onSubmit,
  locale,
  placeholder,
  className,
}: SearchAutocompleteProps) {
  const t = useT('search');
  const { suggestions, loading } = useSearchSuggest(query, locale);
  const [open, setOpen] = useState(false);
  const containerRef = useRef<HTMLDivElement>(null);
  const inputRef = useRef<HTMLInputElement>(null);

  const trimmedQuery = query.trim();
  const hasResults =
    !!suggestions &&
    (suggestions.deals.length > 0 ||
      suggestions.categories.length > 0 ||
      suggestions.tags.length > 0 ||
      suggestions.vendors.length > 0);

  const showDropdown = open && trimmedQuery.length >= 2 && (hasResults || loading);

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

  const handleKeyDown = useCallback(
    (e: React.KeyboardEvent<HTMLInputElement>) => {
      if (e.key === 'Escape') {
        setOpen(false);
        e.preventDefault();
      } else if (e.key === 'Enter') {
        // If cmdk has an active item it will handle selection via onSelect.
        // For a "bare" Enter with no cmdk-selected item, submit full search.
        const selected = containerRef.current?.querySelector('[cmdk-item][aria-selected="true"]');
        if (!selected) {
          onSubmit(query);
          setOpen(false);
          e.preventDefault();
        }
      }
    },
    [query, onSubmit],
  );

  const handleSelect = useCallback(
    (item: SuggestionItem) => {
      onSelect(item);
      setOpen(false);
    },
    [onSelect],
  );

  return (
    <div ref={containerRef} className={cn('relative', className)}>
      <Command shouldFilter={false} loop>
        {/* Input wrapper */}
        <div className="relative">
          {/* Leading search icon */}
          <span
            className="pointer-events-none absolute inset-y-0 start-3 flex items-center"
            aria-hidden
          >
            <Icon name="Search" size="sm" className="text-text-muted" />
          </span>

          <Command.Input
            ref={inputRef}
            value={query}
            onValueChange={onQueryChange}
            onFocus={() => setOpen(true)}
            onKeyDown={handleKeyDown}
            placeholder={placeholder ?? t('placeholder')}
            aria-label={placeholder ?? t('placeholder')}
            className={cn(
              'border-border-default bg-surface-default text-text-primary',
              'w-full rounded-lg border py-2.5 ps-10 pe-10 text-sm',
              'placeholder:text-text-muted',
              'focus-visible:ring-brand-primary-500 focus-visible:ring-2 focus-visible:outline-none',
            )}
          />

          {/* Trailing spinner */}
          {loading && (
            <span className="pointer-events-none absolute inset-y-0 end-3 flex items-center">
              <Spinner variant="inline" size="sm" />
            </span>
          )}
        </div>

        {/* Dropdown */}
        {showDropdown && (
          <Command.List
            className={cn(
              'absolute inset-x-0 top-full z-50 mt-1',
              'border-border-default bg-surface-default',
              'rounded-lg border shadow-lg',
              'max-h-96 overflow-y-auto overscroll-contain',
            )}
          >
            {/* Deals */}
            {suggestions && suggestions.deals.length > 0 && (
              <Command.Group heading={t('suggest_deals')} className={GROUP_CLASS}>
                {suggestions.deals.map((deal) => (
                  <DealSuggestionRow
                    key={deal.id}
                    deal={deal}
                    onSelect={() => handleSelect({ type: 'deal', deal })}
                  />
                ))}
              </Command.Group>
            )}

            {/* Categories */}
            {suggestions && suggestions.categories.length > 0 && (
              <Command.Group heading={t('suggest_categories')} className={GROUP_CLASS}>
                {suggestions.categories.map((entity) => (
                  <EntityRow
                    key={entity.slug}
                    entity={entity}
                    type="category"
                    onSelect={() => handleSelect({ type: 'category', entity })}
                  />
                ))}
              </Command.Group>
            )}

            {/* Tags */}
            {suggestions && suggestions.tags.length > 0 && (
              <Command.Group heading={t('suggest_tags')} className={GROUP_CLASS}>
                {suggestions.tags.map((entity) => (
                  <EntityRow
                    key={entity.slug}
                    entity={entity}
                    type="tag"
                    onSelect={() => handleSelect({ type: 'tag', entity })}
                  />
                ))}
              </Command.Group>
            )}

            {/* Vendors */}
            {suggestions && suggestions.vendors.length > 0 && (
              <Command.Group heading={t('suggest_vendors')} className={GROUP_CLASS}>
                {suggestions.vendors.map((vendor) => (
                  <VendorRow
                    key={vendor.id}
                    vendor={vendor}
                    onSelect={() => handleSelect({ type: 'vendor', vendor })}
                  />
                ))}
              </Command.Group>
            )}

            {/* "Search for X" footer */}
            {trimmedQuery.length >= 2 && (
              <Command.Group className={GROUP_CLASS}>
                <Command.Item
                  value={`search-${trimmedQuery}`}
                  onSelect={() => {
                    onSubmit(trimmedQuery);
                    setOpen(false);
                  }}
                  className={ITEM_CLASS}
                >
                  <Icon name="Search" size="sm" className="text-text-muted shrink-0" aria-hidden />
                  <span className="truncate">
                    {t('suggest_search_for').replace('{{query}}', trimmedQuery)}
                  </span>
                </Command.Item>
              </Command.Group>
            )}
          </Command.List>
        )}
      </Command>
    </div>
  );
}
