import { useState, useCallback } from "react";
import { apiClient } from "@/utils/apiClient";
import { toast } from "sonner";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";
import {
  Collapsible,
  CollapsibleContent,
  CollapsibleTrigger,
} from "@/components/ui/collapsible";
import { Check, ChevronDown, Loader2, Search } from "lucide-react";
import type { SearchProduct } from "./types";

const SEARCH_LIMIT = 100;

interface QuickSearchResult {
  pid: number;
  title: string;
  sku: string;
  barcode: string;
  brand: string;
  line: string;
  regular_price: number;
  image_175: string | null;
}

export function ProductSearch({
  onSelect,
  onLoadAll,
  onNewSearch,
  loadedPids,
}: {
  onSelect: (product: SearchProduct) => void;
  onLoadAll: (pids: number[]) => void;
  onNewSearch: () => void;
  loadedPids: Set<number>;
}) {
  const [searchTerm, setSearchTerm] = useState("");
  const [searchResults, setSearchResults] = useState<QuickSearchResult[]>([]);
  const [totalCount, setTotalCount] = useState(0);
  const [isSearching, setIsSearching] = useState(false);
  const [isLoadingProduct, setIsLoadingProduct] = useState<number | null>(null);
  const [resultsOpen, setResultsOpen] = useState(false);
  const [isFocused, setIsFocused] = useState(false);
  const [fullByPid, setFullByPid] = useState<Map<number, SearchProduct>>(new Map());

  const handleSearch = useCallback(async () => {
    if (!searchTerm.trim()) return;
    setIsSearching(true);
    onNewSearch();
    try {
      const res = await apiClient.get("/api/products/search", {
        params: { q: searchTerm },
      });
      if (res.data.total === 0) {
        const fallback = await apiClient.get("/api/import/search-products", {
          params: { q: searchTerm },
        });
        const fullProducts = fallback.data as SearchProduct[];
        const previews: QuickSearchResult[] = fullProducts.map((p) => ({
          pid: Number(p.pid),
          title: p.title,
          sku: p.sku,
          barcode: p.barcode,
          brand: p.brand,
          line: p.line,
          regular_price: p.regular_price,
          image_175: null,
        }));
        setSearchResults(previews);
        setTotalCount(fullProducts.length);
        setFullByPid(new Map(fullProducts.map((p) => [Number(p.pid), p])));
      } else {
        setSearchResults(res.data.results);
        setTotalCount(res.data.total);
        setFullByPid(new Map());
      }
      setResultsOpen(true);
    } catch {
      toast.error("Search failed");
    } finally {
      setIsSearching(false);
    }
  }, [searchTerm, onNewSearch]);

  const handleSelect = useCallback(
    async (product: QuickSearchResult) => {
      if (loadedPids.has(Number(product.pid))) return;
      const cached = fullByPid.get(Number(product.pid));
      if (cached) {
        onSelect(cached);
        setResultsOpen(false);
        return;
      }
      setIsLoadingProduct(product.pid);
      try {
        const res = await apiClient.get("/api/import/search-products", {
          params: { pid: product.pid },
        });
        const full = (res.data as SearchProduct[])[0];
        if (full) {
          onSelect(full);
          setResultsOpen(false);
        } else {
          toast.error("Could not load full product details");
        }
      } catch {
        toast.error("Failed to load product details");
      } finally {
        setIsLoadingProduct(null);
      }
    },
    [onSelect, loadedPids, fullByPid]
  );

  const handleLoadAll = useCallback(() => {
    const pids = searchResults
      .map((r) => r.pid)
      .filter((pid) => !loadedPids.has(Number(pid)));
    if (pids.length === 0) return;
    onLoadAll(pids);
    setResultsOpen(false);
  }, [searchResults, loadedPids, onLoadAll]);

  const unloadedCount = searchResults.filter(
    (r) => !loadedPids.has(Number(r.pid))
  ).length;
  const isTruncated = totalCount > SEARCH_LIMIT;

  return (
    <div>
      <div className="flex gap-3">
        <Input
          placeholder="Search products…"
          value={searchTerm}
          onChange={(e) => setSearchTerm(e.target.value)}
          onKeyDown={(e) => e.key === "Enter" && handleSearch()}
          onFocus={() => setIsFocused(true)}
          onBlur={() => setIsFocused(false)}
        />
        <Button onClick={handleSearch} disabled={isSearching}>
          {isSearching ? (
            <Loader2 className="h-4 w-4 animate-spin" />
          ) : (
            <Search className="h-4 w-4" />
          )}
        </Button>
      </div>
      {(isFocused || searchResults.length === 0) && (
        <p className="text-xs text-muted-foreground mt-1 ml-3">
          Search by name, item number, UPC, company, supplier, supplier id, notions #, line, subline, artist
        </p>
      )}

      {searchResults.length > 0 && (
        <Collapsible open={resultsOpen} onOpenChange={setResultsOpen} className="mt-3">
          <div className="flex items-center justify-between">
            <CollapsibleTrigger asChild>
              <Button variant="ghost" size="sm" className="gap-1 px-2 text-muted-foreground">
                <ChevronDown
                  className={`h-4 w-4 transition-transform ${resultsOpen ? "" : "-rotate-90"}`}
                />
                {isTruncated
                  ? `Showing ${SEARCH_LIMIT} of ${totalCount} results`
                  : `${totalCount} ${totalCount === 1 ? "result" : "results"}`}
              </Button>
            </CollapsibleTrigger>
            {unloadedCount > 0 && (
              <Button variant="outline" size="sm" onClick={handleLoadAll}>
                Load all results
              </Button>
            )}
          </div>

          <CollapsibleContent>
            <div className="border rounded-md mt-2 max-h-80 overflow-auto">
              <Table>
                <TableHeader>
                  <TableRow>
                    <TableHead className="sticky top-0 bg-background">Name</TableHead>
                    <TableHead className="sticky top-0 bg-background">Item Number</TableHead>
                    <TableHead className="sticky top-0 bg-background">Brand</TableHead>
                    <TableHead className="sticky top-0 bg-background">Line</TableHead>
                    <TableHead className="sticky top-0 bg-background text-right">
                      Price
                    </TableHead>
                  </TableRow>
                </TableHeader>
                <TableBody>
                  {searchResults.map((product) => {
                    const isLoaded = loadedPids.has(Number(product.pid));
                    return (
                      <TableRow
                        key={product.pid}
                        className={`${isLoaded ? "opacity-50" : "cursor-pointer hover:bg-muted/50"} ${isLoadingProduct === product.pid ? "opacity-50" : ""}`}
                        onClick={() =>
                          !isLoadingProduct && !isLoaded && handleSelect(product)
                        }
                      >
                        <TableCell className="max-w-[300px] truncate">
                          {isLoadingProduct === product.pid && (
                            <Loader2 className="h-3 w-3 animate-spin inline mr-2" />
                          )}
                          {isLoaded && (
                            <Check className="h-3 w-3 inline mr-2 text-green-600" />
                          )}
                          {product.title}
                        </TableCell>
                        <TableCell>{product.sku}</TableCell>
                        <TableCell>{product.brand}</TableCell>
                        <TableCell>{product.line}</TableCell>
                        <TableCell className="text-right">
                          $
                          {Number(product.regular_price)?.toFixed(2) ??
                            product.regular_price}
                        </TableCell>
                      </TableRow>
                    );
                  })}
                </TableBody>
              </Table>
            </div>
            {isTruncated && (
              <p className="text-xs text-muted-foreground mt-2">
                Showing only the first {SEARCH_LIMIT} of {totalCount} matches. Refine your search to find specific products.
              </p>
            )}
          </CollapsibleContent>
        </Collapsible>
      )}
    </div>
  );
}
