import { sql } from 'drizzle-orm'
import type { useDB } from '../../utils/database'

/**
 * Pagination parameters extracted from query string
 */
export interface PaginationParams {
  page: number
  pageSize: number
}

/**
 * Paginated result with metadata
 */
export interface PaginatedResult<T> {
  data: T[]
  total: number
  page: number
  pageSize: number
  totalPages: number
}

/**
 * Create pagination parameters from query string
 * Validates and normalizes page and pageSize values
 *
 * @param query - Query parameters from request
 * @param defaultPageSize - Default page size (default: 20)
 * @param maxPageSize - Maximum allowed page size (default: 100)
 * @returns Normalized pagination parameters
 *
 * @example
 * const params = createPaginationParams(getQuery(event))
 * // { page: 1, pageSize: 20 }
 */
export function createPaginationParams(
  query: Record<string, unknown>,
  defaultPageSize = 20,
  maxPageSize = 100
): PaginationParams {
  return {
    page: Math.max(1, Number(query.page) || 1),
    pageSize: Math.min(maxPageSize, Math.max(1, Number(query.pageSize) || defaultPageSize))
  }
}

/**
 * Calculate offset from pagination parameters
 */
export function calculateOffset(params: PaginationParams): number {
  return (params.page - 1) * params.pageSize
}

/**
 * Calculate total pages from total count and page size
 */
export function calculateTotalPages(total: number, pageSize: number): number {
  return Math.ceil(total / pageSize)
}

/**
 * Count total records for a table with optional where clause
 *
 * @param db - Database instance from useDB()
 * @param table - Table to count (Drizzle table object)
 * @param whereClause - Optional where clause (e.g., and(...) or eq(...))
 * @returns Total count of records
 *
 * @example
 * const db = useDB()
 * const total = await countRecords(db, user, whereClause)
 */
export async function countRecords(
  db: ReturnType<typeof useDB>,
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  table: any,
  whereClause?: unknown
): Promise<number> {
  const countQuery = db.select({ count: sql<number>`count(*)` }).from(table)

  // Apply where clause if provided
  const countResult = whereClause
    ? await (countQuery as { where: (clause: unknown) => Promise<Array<{ count: number }>> }).where(whereClause)
    : await countQuery

  return Number(countResult[0]?.count ?? 0)
}

/**
 * Create a paginated result object
 *
 * @param data - Array of data items
 * @param total - Total count of all records
 * @param params - Pagination parameters
 * @returns Paginated result with metadata
 *
 * @example
 * const result = createPaginatedResult(users, total, params)
 * // { data: [...], total: 100, page: 1, pageSize: 20, totalPages: 5 }
 */
export function createPaginatedResult<T>(
  data: T[],
  total: number,
  params: PaginationParams
): PaginatedResult<T> {
  return {
    data,
    total,
    page: params.page,
    pageSize: params.pageSize,
    totalPages: calculateTotalPages(total, params.pageSize)
  }
}
