import { useInfiniteQuery, useQuery } from "@tanstack/react-query";
import { useSearchParams } from "@remix-run/react";
import {
  ApiSearchV1ListRequest,
} from "../../src/api/types";
import {
  ProductSearchResult,
  SearchResponse,
  SellerSearchResult,
} from "../../src/api/types/models";
import { createSearchSystemApi } from "~/utils/api-client-factory";

/**
 * Hook to fetch autocomplete suggestions from the API
 * Cancels previous requests when a new search is initiated
 */
export const useSearchAutocomplete = (query: string) => {
  return useQuery({
    queryKey: ["searchAutocomplete", query],
    queryFn: async ({ signal }) => {
      if (!query || query.trim() === "") {
        return { suggestions: [] };
      }

      const searchApi = createSearchSystemApi();

      // Create an init override function that includes the signal
      const initOverrides = { signal };

      try {
        return await searchApi.apiSearchV1AutocompleteList(
          { q: query },
          initOverrides
        );
      } catch (error) {
        // If the request was aborted, return empty results
        if (error instanceof DOMException && error.name === "AbortError") {
          return { suggestions: [] };
        }
        throw error;
      }
    },
    enabled: query.trim().length > 0,
    staleTime: 1000 * 10, // 10 seconds
    refetchOnWindowFocus: false,
  });
};

/**
 * Hook to fetch search results with infinite scrolling
 * Reads search params from URL and fetches data accordingly
 */
export const useSearchInfinite = (routeQueryParam?: string) => {
  const [searchParams] = useSearchParams();

  // Get search query from route param and decode it
  const query = routeQueryParam ? decodeURIComponent(routeQueryParam) : "";

  // Get other search parameters from URL
  const orderParam = searchParams.get("order");
  const priceMinParam = searchParams.get("priceMin");
  const priceMaxParam = searchParams.get("priceMax");

  // Build search parameters
  const searchQueryParams: ApiSearchV1ListRequest = {
    q: query,
  };

  // Add sortBy parameter based on order
  if (orderParam) {
    // Map our order values to what the API expects in sortBy
    switch (orderParam) {
      case "cheap":
        searchQueryParams.sortBy = "price";
        break;
      case "expensive":
        searchQueryParams.sortBy = "-price"; // Negative for descending
        break;
      case "newest":
        searchQueryParams.sortBy = "newest";
        break;
      default:
        searchQueryParams.sortBy = orderParam;
    }
  }

  // Add price filters if they exist
  if (priceMinParam) searchQueryParams.priceMin = parseInt(priceMinParam, 10);
  if (priceMaxParam) searchQueryParams.priceMax = parseInt(priceMaxParam, 10);

  return useInfiniteQuery({
    queryKey: ["search", searchQueryParams],
    queryFn: async ({ pageParam = 1 }) => {
      const searchApi = createSearchSystemApi();
      return await searchApi.apiSearchV1List({
        ...searchQueryParams,
        page: pageParam as number,
      });
    },
    getNextPageParam: (lastPage: SearchResponse, allPages) => {
      if (!lastPage || !lastPage.products || !lastPage.products.length) {
        return undefined;
      }

      // Use the length of allPages to determine the next page number
      const currentPage = allPages.length;

      // If there are products and there should be more pages, return next page number
      if (lastPage.products.length > 0) {
        return currentPage + 1;
      }

      return undefined;
    },
    initialPageParam: 1,
    enabled: !!query, // Only run query if search query exists
  });
};

// Re-export types from the API for convenience
export type { ProductSearchResult, SellerSearchResult, SearchResponse };
