import { useState, useCallback, useMemo } from 'react';

export interface QueryFilters {
  [key: string]: any;
}

export interface SortConfig {
  field: string;
  order: 'asc' | 'desc';
}

export interface UseQueryBuilderResult {
  filters: QueryFilters;
  search: string;
  sort: SortConfig | null;
  page: number;
  pageSize: number;
  queryString: string;
  queryParams: URLSearchParams;
  setFilter: (key: string, value: any) => void;
  removeFilter: (key: string) => void;
  clearFilters: () => void;
  setSearch: (search: string) => void;
  setSort: (field: string, order: 'asc' | 'desc') => void;
  toggleSort: (field: string) => void;
  clearSort: () => void;
  setPage: (page: number) => void;
  setPageSize: (size: number) => void;
  reset: () => void;
}

/**
 * Hook for building query strings with filters, search, sort, and pagination
 * Works seamlessly with the backend QueryParser
 * 
 * @example
 * const { queryString, setFilter, setSearch, setSort } = useQueryBuilder();
 * setFilter('published', true);
 * setSearch('football');
 * setSort('created_at', 'desc');
 * // queryString: "published=true&search=football&sort=created_at:desc&page=1&page_size=20"
 */
export function useQueryBuilder(initialPageSize: number = 20): UseQueryBuilderResult {
  const [filters, setFilters] = useState<QueryFilters>({});
  const [search, setSearchState] = useState('');
  const [sort, setSortState] = useState<SortConfig | null>(null);
  const [page, setPageState] = useState(1);
  const [pageSize, setPageSizeState] = useState(initialPageSize);

  const setFilter = useCallback((key: string, value: any) => {
    setFilters((prev) => ({ ...prev, [key]: value }));
    setPageState(1); // Reset to first page when filter changes
  }, []);

  const removeFilter = useCallback((key: string) => {
    setFilters((prev) => {
      const newFilters = { ...prev };
      delete newFilters[key];
      return newFilters;
    });
    setPageState(1);
  }, []);

  const clearFilters = useCallback(() => {
    setFilters({});
    setPageState(1);
  }, []);

  const setSearch = useCallback((searchTerm: string) => {
    setSearchState(searchTerm);
    setPageState(1); // Reset to first page when search changes
  }, []);

  const setSort = useCallback((field: string, order: 'asc' | 'desc') => {
    setSortState({ field, order });
  }, []);

  const toggleSort = useCallback((field: string) => {
    setSortState((prev) => {
      if (!prev || prev.field !== field) {
        return { field, order: 'asc' };
      }
      if (prev.order === 'asc') {
        return { field, order: 'desc' };
      }
      return null; // Clear sort
    });
  }, []);

  const clearSort = useCallback(() => {
    setSortState(null);
  }, []);

  const setPage = useCallback((newPage: number) => {
    setPageState(newPage);
  }, []);

  const setPageSize = useCallback((size: number) => {
    setPageSizeState(size);
    setPageState(1); // Reset to first page
  }, []);

  const reset = useCallback(() => {
    setFilters({});
    setSearchState('');
    setSortState(null);
    setPageState(1);
    setPageSizeState(initialPageSize);
  }, [initialPageSize]);

  const queryParams = useMemo(() => {
    const params = new URLSearchParams();

    // Add filters
    Object.entries(filters).forEach(([key, value]) => {
      if (value !== undefined && value !== null && value !== '') {
        params.append(key, String(value));
      }
    });

    // Add search
    if (search) {
      params.append('search', search);
    }

    // Add sort
    if (sort) {
      params.append('sort', `${sort.field}:${sort.order}`);
    }

    // Add pagination
    params.append('page', String(page));
    params.append('page_size', String(pageSize));

    return params;
  }, [filters, search, sort, page, pageSize]);

  const queryString = useMemo(() => {
    return queryParams.toString();
  }, [queryParams]);

  return {
    filters,
    search,
    sort,
    page,
    pageSize,
    queryString,
    queryParams,
    setFilter,
    removeFilter,
    clearFilters,
    setSearch,
    setSort,
    toggleSort,
    clearSort,
    setPage,
    setPageSize,
    reset,
  };
}
