import { Injectable } from '@nestjs/common';

/**
 * PaginatorService - Service for calculating pagination offsets and limits
 *
 * This service provides utilities for implementing pagination in database queries
 * and API responses. It calculates the appropriate OFFSET value for SQL queries
 * based on page number and items per page.
 *
 * Features:
 * - Calculates SQL OFFSET for paginated queries
 * - Configurable default items per page
 * - Input validation with reasonable defaults
 * - Protection against excessively large page sizes
 *
 * Pagination formula: OFFSET = (page - 1) * per_page
 *
 * @example
 * // Calculate offset for page 3 with 20 items per page
 * const offset = paginatorService.getSkipOffset({ page: 3, per_page: 20 });
 * // Returns: 40 (skip first 40 items, show items 41-60)
 *
 * @example
 * // Use in TypeORM query
 * const users = await userRepository.find({
 *   skip: paginatorService.getSkipOffset({ page, per_page }),
 *   take: per_page
 * });
 */
@Injectable()
export class PaginatorService {
  /**
   * Default items per page
   *
   * Used when per_page is not specified or exceeds maximum allowed value.
   *
   * @default 20
   */
  protected perPage: number;

  /**
   * Default page number
   *
   * Used when page is not specified or is invalid.
   *
   * @default 1
   */
  protected page: number;

  /**
   * Maximum allowed items per page
   *
   * Prevents clients from requesting excessively large page sizes
   * that could impact database performance.
   *
   * @default 50
   */
  protected maxPerPage: number;

  constructor() {
    this.perPage = 20; // Default items per page
    this.page = 1; // Default page number
    this.maxPerPage = 50; // Maximum items per page
  }

  /**
   * Calculates the OFFSET value for SQL pagination queries
   *
   * Determines how many records to skip based on page number and
   * items per page, with input validation and reasonable defaults.
   *
   * Formula: OFFSET = (page - 1) * per_page
   *
   * @param filter - Object containing pagination parameters
   * @param filter.per_page - Items per page (optional, defaults to 20, max 50)
   * @param filter.page - Page number (optional, defaults to 1, must be positive)
   * @returns The OFFSET value (number of records to skip)
   *
   * @example
   * // Page 1, 20 items per page: offset = 0
   * // Page 3, 10 items per page: offset = 20
   * // Page 2, 50 items per page: offset = 50
   *
   * @note Page numbers start at 1 (not 0)
   * @note Maximum per_page is capped at 50 for performance
   * @note Invalid inputs fall back to reasonable defaults
   */
  getSkipOffset(filter: { per_page?: number; page?: number }): number {
    // Validate and sanitize items per page
    const perPage = this.validatePerPage(filter.per_page);

    // Validate and sanitize page number
    const page = this.validatePage(filter.page);

    // Calculate offset: (page - 1) * per_page
    return (page - 1) * perPage;
  }

  /**
   * Validates and sanitizes the per_page parameter
   *
   * Ensures per_page is a positive number and doesn't exceed maximum limit.
   *
   * @param per_page - Requested items per page
   * @returns Sanitized items per page (between 1 and maxPerPage)
   */
  protected validatePerPage(per_page?: number): number {
    if (!per_page || per_page < 1) {
      return this.perPage; // Use default if invalid
    }

    // Cap at maximum allowed to prevent performance issues
    return Math.min(per_page, this.maxPerPage);
  }

  /**
   * Validates and sanitizes the page parameter
   *
   * Ensures page is a positive number.
   *
   * @param page - Requested page number
   * @returns Sanitized page number (at least 1)
   */
  protected validatePage(page?: number): number {
    if (!page || page < 1) {
      return this.page; // Use default if invalid
    }

    return page;
  }

  /**
   * Enhanced methods that could be added:
   *
   * getPaginationMetadata(totalItems: number, currentPage: number, perPage: number): PaginationMetadata {
   *   // Calculate total pages, next page, previous page, etc.
   * }
   *
   * generatePaginationLinks(baseUrl: string, currentPage: number, totalPages: number): PaginationLinks {
   *   // Generate first, last, next, prev links for API responses
   * }
   *
   * validatePaginationParams(page: number, perPage: number): ValidationResult {
   *   // Comprehensive validation with detailed error messages
   * }
   *
   * getTakeLimit(per_page?: number): number {
   *   // Returns the LIMIT value for SQL queries (same as per_page)
   * }
   */
}
