/**
 * Generic hook for loading list data from an API endpoint.
 *
 * Composes useFetchData to provide a list-specific interface where initial
 * data defaults to an empty array and the result is typed as `items: TItem[]`.
 */
import { useFetchData } from "./useFetchData";
import type { FetchError } from "../types/api";

export interface UseListDataOptions<TResponse, TItem> {
  /** Async function that accepts an AbortSignal for cancellation. */
  fetcher: (signal: AbortSignal) => Promise<TResponse>;
  /** Synchronous selector to extract items array from response. */
  selector: (response: TResponse) => TItem[];
  /** Human-readable error message used as fallback if fetch fails. */
  errorMessage: string;
  /** Optional callback invoked after successful fetch with full response. */
  onSuccess?: (response: TResponse) => void;
  /** Initial items array. Defaults to empty array. */
  initialItems?: TItem[];
}

export interface UseListDataResult<TItem> {
  /** The extracted items array from the most recent successful fetch. */
  items: TItem[];
  /** True while a fetch is in-flight, false when complete. */
  loading: boolean;
  /** Typed error or null. Check `error?.type` to handle specific failure modes. */
  error: FetchError | null;
  /** Trigger a fresh fetch. Cancels any in-flight request first. */
  refresh: () => void;
}

/**
 * Load a list response and expose refresh semantics with abort support.
 *
 * Provides typed error handling through the `error` property, which is either
 * `null` or a discriminated `FetchError` union. Use the error's `type` field
 * to determine how to handle it:
 *
 * - `"api_error"`: Server returned HTTP error (check `status` for 401/403/50x)
 * - `"network_error"`: Network, DNS, or JSON parse failure
 * - `"abort_error"`: Request was cancelled (typically silently ignored by hook)
 *
 * @param options - Configuration options
 * @returns List data, loading state, typed error, and refresh callback
 */
export function useListData<TResponse, TItem>(
  options: UseListDataOptions<TResponse, TItem>,
): UseListDataResult<TItem> {
  const { fetcher, selector, errorMessage, onSuccess, initialItems } = options;

  const { data, loading, error, refresh } = useFetchData({
    fetcher,
    selector,
    errorMessage,
    onSuccess,
    initialData: initialItems ?? [],
  });

  return { items: data ?? [], loading, error, refresh };
}
