import { type CoreResponse } from '../../core/index.js';
import type { ICoreResponse } from '../../core_base/types.js';

/**
 * Pagination strategy options
 */
export enum PaginationStrategy {
  OFFSET = 'offset', // Uses page & limit parameters
  CURSOR = 'cursor', // Uses a cursor/token for next page
  LINK_HEADER = 'link', // Uses Link headers
  CUSTOM = 'custom', // Uses a custom pagination handler
}

/**
 * Configuration for offset-based pagination
 */
export interface OffsetPaginationConfig {
  strategy: PaginationStrategy.OFFSET;
  pageParam?: string; // Parameter name for page number (default: "page")
  limitParam?: string; // Parameter name for page size (default: "limit")
  startPage?: number; // Starting page number (default: 1)
  pageSize?: number; // Number of items per page (default: 20)
  totalPath?: string; // JSON path to total item count (default: "total")
}

/**
 * Configuration for cursor-based pagination
 */
export interface CursorPaginationConfig {
  strategy: PaginationStrategy.CURSOR;
  cursorParam?: string; // Parameter name for cursor (default: "cursor")
  cursorPath?: string; // JSON path to next cursor (default: "nextCursor")
  hasMorePath?: string; // JSON path to check if more items exist (default: "hasMore")
}

/**
 * Configuration for Link header-based pagination
 */
export interface LinkPaginationConfig {
  strategy: PaginationStrategy.LINK_HEADER;
  // No additional config needed, uses standard Link header format
}

/**
 * Configuration for custom pagination
 */
export interface CustomPaginationConfig {
  strategy: PaginationStrategy.CUSTOM;
  hasNextPage: (response: ICoreResponse<any>) => boolean;
  getNextPageParams: (
    response: ICoreResponse<any>,
    currentParams: Record<string, string>,
  ) => Record<string, string>;
}

/**
 * Union type of all pagination configurations
 */
export type TPaginationConfig =
  | OffsetPaginationConfig
  | CursorPaginationConfig
  | LinkPaginationConfig
  | CustomPaginationConfig;

/**
 * Interface for a paginated response
 */
export interface TPaginatedResponse<T> {
  items: T[]; // Current page items
  hasNextPage: boolean; // Whether there are more pages
  getNextPage: () => Promise<TPaginatedResponse<T>>; // Function to get the next page
  getAllPages: () => Promise<T[]>; // Function to get all remaining pages and combine
  response: ICoreResponse<any>; // Original response
}
