"use client";

import React, { useState, useEffect, useRef } from "react";
import { Input } from "@/components/ui/input";
import { SearchIcon, X } from "lucide-react";
import { searchProducts } from "@/lib/product-actions";
import { ProductDetails } from "@/types/product";
import { useRouter } from "next/navigation";
import Link from "next/link";
import { Spinner } from "@/components/ui/Spinner";
import { formatCurrency } from "@/lib/format";
import { Kbd } from "@/components/ui/kbd";
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip";
import { logClientError } from "@/actions/logging";

interface SearchOptionProps {
  product: ProductDetails;
  isSelected: boolean;
  optionId: string;
  onClick: () => void;
}

/**
 * ⚡ Optimization: Memoized Search Option
 * Prevents re-renders of all search results when navigating with keyboard.
 * Only the newly selected and previously selected items will re-render.
 */
const SearchOption = React.memo(({ product, isSelected, optionId, onClick }: SearchOptionProps) => {
  return (
    <li id={optionId} role="option" aria-selected={isSelected}>
      <Link
        href={`/product/${product.id}`}
        className={`flex items-center hover:bg-accent hover:text-accent-foreground cursor-pointer p-2 transition-colors ${
          isSelected ? "bg-accent text-accent-foreground" : ""
        }`}
        onClick={onClick}
      >
        <div className="flex items-center justify-center text-muted-foreground">
          <SearchIcon size={20} aria-hidden="true" />
        </div>
        <p className="ml-4 flex-1 overflow-hidden truncate mr-4">
          {product.title}
        </p>
        <div className="ml-auto">
          {formatCurrency(product.price)}
        </div>
      </Link>
    </li>
  );
});

SearchOption.displayName = "SearchOption";

export const SearchBar = () => {
  const [searchQuery, setSearchQuery] = useState("");
  const [searchResults, setSearchResults] = useState<ProductDetails[]>([]);
  const [selectedIndex, setSelectedIndex] = useState(-1);
  const [isFocused, setIsFocused] = useState(false);
  const [isCleared, setIsCleared] = useState(false);
  const searchBarRef = useRef<HTMLDivElement>(null);
  const inputRef = useRef<HTMLInputElement>(null);
  const debounceTimeout = useRef<NodeJS.Timeout | null>(null);
  const searchCache = useRef<Map<string, ProductDetails[]>>(new Map());
  const [noResults, setNoResults] = useState(false);
  const [isLoading, setIsLoading] = useState(false);
  const [isMac, setIsMac] = useState(false);

  useEffect(() => {
    setIsMac(navigator.platform.toUpperCase().indexOf("MAC") >= 0);
    return () => {
      if (debounceTimeout.current) clearTimeout(debounceTimeout.current);
    };
  }, []);

  useEffect(() => {
    const down = (e: KeyboardEvent) => {
      if (e.key === "k" && (e.metaKey || e.ctrlKey)) {
        e.preventDefault();
        inputRef.current?.focus();
      }
    };

    document.addEventListener("keydown", down);
    return () => document.removeEventListener("keydown", down);
  }, []);

  const clearSearch = () => {
    setSearchQuery("");
    setSearchResults([]);
    setNoResults(false);
    setSelectedIndex(-1);
    setIsCleared(true);
    inputRef.current?.focus();
  };

  const handleSearch = (event: React.ChangeEvent<HTMLInputElement>) => {
    const query = event.target.value;
    setSearchQuery(query);
    setIsCleared(false);

    if (debounceTimeout.current) clearTimeout(debounceTimeout.current);

    debounceTimeout.current = setTimeout(async () => {
      const trimmedQuery = query.trim();
      if (trimmedQuery.length > 2) {
        /*
          ⚡ Optimization: Client-side Search Cache
          Check if results for this query are already cached to avoid redundant server round-trips.
          Expected Impact: Instant results for repeated queries; reduced server load.
        */
        if (searchCache.current.has(trimmedQuery)) {
          const cachedResults = searchCache.current.get(trimmedQuery)!;
          setSearchResults(cachedResults);
          setNoResults(cachedResults.length === 0);
          setSelectedIndex(-1);
          return;
        }

        setIsLoading(true);
        try {
          const response = await searchProducts({ 
            page: 1, 
            pageSize: 10, 
            query: trimmedQuery, 
            requestType: "search",
            sortOrder: "ASC"
          });
          
          if (response.success) {
            const results = response.data;
            setSearchResults(results.documents);
            searchCache.current.set(trimmedQuery, results.documents);
            setSelectedIndex(-1);
            setNoResults(results.documents.length === 0);
          } else {
            throw new Error(response.error);
          }
        } catch (error: any) {
          console.error("Error searching products:", error);
          logClientError("Search error", { 
            query: trimmedQuery,
            error: error.message || String(error),
            stack: error.stack 
          });
          setNoResults(true);
        } finally {
          setIsLoading(false);
        }
      } else {
        setSearchResults([]);
        setNoResults(false);
      }
    }, 320);
  };

  const handleKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {
    if (event.key === "ArrowDown") {
      event.preventDefault();
      if (searchResults.length > 0) {
        setSelectedIndex((prevIndex) =>
          prevIndex < searchResults.length - 1 ? prevIndex + 1 : 0,
        );
      }
    } else if (event.key === "ArrowUp") {
      event.preventDefault();
      if (searchResults.length > 0) {
        setSelectedIndex((prevIndex) =>
          prevIndex > 0 ? prevIndex - 1 : searchResults.length - 1,
        );
      }
    } else if (event.key === "Enter" && selectedIndex >= 0) {
      event.preventDefault();
      router.push(`/product/${searchResults[selectedIndex].id}`);
      setIsFocused(false);
    } else if (event.key === "Escape") {
      setIsFocused(false);
      setSelectedIndex(-1);
    }
  };

  useEffect(() => {
    const handleClickOutside = (event: MouseEvent) => {
      if (
        searchBarRef.current &&
        !searchBarRef.current.contains(event.target as Node)
      ) {
        setIsFocused(false);
        setSelectedIndex(-1);
      }
    };

    document.addEventListener("mousedown", handleClickOutside);
    return () => {
      document.removeEventListener("mousedown", handleClickOutside);
    };
  }, []);

  const router = useRouter();

  const handleSubmit = () => {
    router.push(`/search?q=${searchQuery}`);
  };

  /**
   * ⚡ Optimization: Stable Click Handler
   * Prevents SearchOption from re-rendering due to function reference changes.
   */
  const handleOptionClick = React.useCallback(() => {
    setIsFocused(false);
  }, []);

  const listboxId = "search-results-listbox";
  const getOptionId = (index: number) => `search-option-${index}`;

  return (
    <div
      ref={searchBarRef}
      className="relative w-full sm:w-3/4 md:w-2/3 lg:w-7/12 lg:block hidden"
    >
      <div className="sr-only" role="status" aria-live="polite">
        {isCleared ? (
          "Suche gelöscht"
        ) : (
          <>
            {isLoading && "Suche läuft..."}
            {!isLoading &&
              searchResults.length > 0 &&
              `${searchResults.length} ${
                searchResults.length === 1 ? "Ergebnis" : "Ergebnisse"
              } gefunden`}
            {!isLoading && noResults && "Keine Ergebnisse gefunden"}
          </>
        )}
      </div>
      <form
        onSubmit={(e) => {
          e.preventDefault();
          handleSubmit();
        }}
        className="relative"
      >
        <Input
          ref={inputRef}
          type="text"
          placeholder="Online-Shop durchsuchen..."
          aria-label="Produktsuche"
          role="combobox"
          aria-autocomplete="list"
          aria-expanded={isFocused && (searchResults.length > 0 || noResults)}
          aria-haspopup="listbox"
          aria-controls={listboxId}
          aria-activedescendant={
            selectedIndex >= 0 ? getOptionId(selectedIndex) : undefined
          }
          className="rounded-full pl-4 pr-20 w-full"
          value={searchQuery}
          onChange={handleSearch}
          onKeyDown={handleKeyDown}
          onFocus={() => setIsFocused(true)}
        />
        <div className="absolute right-4 top-1/2 -translate-y-1/2 flex items-center gap-2">
          <TooltipProvider delayDuration={0}>
          {!searchQuery && !isLoading && (
            <div className="pointer-events-none hidden sm:block" aria-hidden="true">
              <Kbd className="bg-transparent border-none text-muted-foreground">
                <span className="text-xs">{isMac ? "⌘" : "Ctrl"}</span>
                <span className="text-xs">K</span>
              </Kbd>
            </div>
          )}
          {searchQuery && (
            <Tooltip>
              <TooltipTrigger asChild>
                <button type="button" onClick={clearSearch} aria-label="Suche löschen" className="text-muted-foreground hover:text-foreground transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 rounded-full p-1">
                  <X size={16} aria-hidden="true" />
                </button>
              </TooltipTrigger>
              <TooltipContent side="top">Suche löschen</TooltipContent>
            </Tooltip>
          )}
          {isLoading && <Spinner className="text-muted-foreground" />}
          <Tooltip>
            <TooltipTrigger asChild>
              <button type="submit" aria-label="Suche starten" className="text-foreground hover:text-foreground/80 transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 rounded-sm">
                <SearchIcon size={24} aria-hidden="true" />
              </button>
            </TooltipTrigger>
            <TooltipContent side="top">Suche starten</TooltipContent>
          </Tooltip>
          </TooltipProvider>
        </div>
      </form>
      {isFocused && (searchResults.length > 0 || noResults) && (
        <div className="absolute bg-popover text-popover-foreground border shadow-md rounded-lg w-full mt-2 z-50 overflow-hidden">
          {searchResults.length > 0 ? (
            <ul id={listboxId} role="listbox" className="py-1">
              {searchResults.map((product, index) => (
                <SearchOption
                  key={product.id}
                  product={product}
                  optionId={getOptionId(index)}
                  isSelected={index === selectedIndex}
                  onClick={handleOptionClick}
                />
              ))}
            </ul>
          ) : (
            <div className="p-3 text-sm text-muted-foreground text-center">
              Keine Ergebnisse gefunden
            </div>
          )}
        </div>
      )}
    </div>
  );
};
