<?php
/**
 * Register a custom REST API endpoint.
 *
 * Usage: GET /wp-json/my-plugin/v1/items?per_page=10&page=1
 */
add_action( 'rest_api_init', function () {
    register_rest_route( 'my-plugin/v1', '/items', array(
        'methods'             => WP_REST_Server::READABLE,
        'callback'            => 'my_plugin_get_items',
        'permission_callback' => 'my_plugin_items_permission',
        'args'                => array(
            'per_page' => array(
                'type'              => 'integer',
                'default'           => 10,
                'minimum'           => 1,
                'maximum'           => 100,
                'sanitize_callback' => 'absint',
            ),
            'page'     => array(
                'type'              => 'integer',
                'default'           => 1,
                'minimum'           => 1,
                'sanitize_callback' => 'absint',
            ),
        ),
    ) );
} );

/**
 * Permission callback — require authentication.
 */
function my_plugin_items_permission( WP_REST_Request $request ): bool {
    return current_user_can( 'read' );
}

/**
 * Endpoint callback — return paginated items.
 */
function my_plugin_get_items( WP_REST_Request $request ): WP_REST_Response {
    $per_page = $request->get_param( 'per_page' );
    $page     = $request->get_param( 'page' );

    // Example: fetch from a custom table.
    global $wpdb;
    $table  = $wpdb->prefix . 'my_items';
    $offset = ( $page - 1 ) * $per_page;

    $total = (int) $wpdb->get_var( "SELECT COUNT(*) FROM {$table}" );
    $items = $wpdb->get_results(
        $wpdb->prepare(
            "SELECT * FROM {$table} ORDER BY created_at DESC LIMIT %d OFFSET %d",
            $per_page,
            $offset
        )
    );

    $response = rest_ensure_response( $items );
    $response->header( 'X-WP-Total', $total );
    $response->header( 'X-WP-TotalPages', ceil( $total / $per_page ) );

    return $response;
}