import { useState, useEffect, useCallback } from 'react';
import { api } from '../services/api';
import { AxiosError } from 'axios';

export interface PaginationMeta {
  page: number;
  page_size: number;
  total: number;
  total_pages: number;
  has_next: boolean;
  has_prev: boolean;
}

export interface PaginatedResponse<T> {
  success: boolean;
  message?: string;
  data: T[];
  meta: PaginationMeta;
}

export interface QueryParams {
  page?: number;
  page_size?: number;
  search?: string;
  sort?: string;
  [key: string]: any;
}

export interface UsePaginatedDataResult<T> {
  data: T[];
  meta: PaginationMeta | null;
  loading: boolean;
  error: string | null;
  refresh: () => void;
  setPage: (page: number) => void;
  setPageSize: (size: number) => void;
  setSearch: (search: string) => void;
  setSort: (field: string, order: 'asc' | 'desc') => void;
  setFilters: (filters: Record<string, any>) => void;
  updateQueryParams: (params: Partial<QueryParams>) => void;
}

/**
 * Hook for fetching paginated data with search, sort, and filters
 * Automatically handles pagination, loading states, and errors
 * 
 * @example
 * const { data, meta, loading, setSearch, setPage } = usePaginatedData<Article>('/articles');
 */
export function usePaginatedData<T = any>(
  endpoint: string,
  initialParams: QueryParams = {}
): UsePaginatedDataResult<T> {
  const [data, setData] = useState<T[]>([]);
  const [meta, setMeta] = useState<PaginationMeta | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [queryParams, setQueryParams] = useState<QueryParams>({
    page: 1,
    page_size: 20,
    ...initialParams,
  });

  const fetchData = useCallback(async () => {
    try {
      setLoading(true);
      setError(null);

      // Build query string
      const params = new URLSearchParams();
      Object.entries(queryParams).forEach(([key, value]) => {
        if (value !== undefined && value !== null && value !== '') {
          params.append(key, String(value));
        }
      });

      const response = await api.get<PaginatedResponse<T>>(
        `${endpoint}?${params.toString()}`
      );

      if (response.data.success) {
        setData(response.data.data || []);
        setMeta(response.data.meta || null);
      } else {
        setError(response.data.message || 'Failed to fetch data');
      }
    } catch (err) {
      const axiosError = err as AxiosError<{ error: string }>;
      setError(
        axiosError.response?.data?.error || 
        axiosError.message || 
        'An error occurred'
      );
      setData([]);
      setMeta(null);
    } finally {
      setLoading(false);
    }
  }, [endpoint, queryParams]);

  useEffect(() => {
    fetchData();
  }, [fetchData]);

  const updateQueryParams = useCallback((params: Partial<QueryParams>) => {
    setQueryParams((prev) => ({ ...prev, ...params }));
  }, []);

  const setPage = useCallback((page: number) => {
    updateQueryParams({ page });
  }, [updateQueryParams]);

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

  const setSearch = useCallback((search: string) => {
    updateQueryParams({ search, page: 1 }); // Reset to first page
  }, [updateQueryParams]);

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

  const setFilters = useCallback((filters: Record<string, any>) => {
    updateQueryParams({ ...filters, page: 1 }); // Reset to first page
  }, [updateQueryParams]);

  const refresh = useCallback(() => {
    fetchData();
  }, [fetchData]);

  return {
    data,
    meta,
    loading,
    error,
    refresh,
    setPage,
    setPageSize,
    setSearch,
    setSort,
    setFilters,
    updateQueryParams,
  };
}
