<?php

namespace WC_Affiliate\Traits;

use WP_Error;
use WP_REST_Request;
use WP_REST_Response;

defined( 'ABSPATH' ) || exit;

/**
 * Trait Rest
 *
 * This trait provides methods to register REST API routes and handle JSON responses in the WordPress plugin.
 *
 * @package WC_Affiliate
 */
trait Rest {

	/**
	 * Creates a successful REST API response.
	 *
	 * @param mixed  $data        The response data.
	 * @param string $message     Optional success message.
	 * @param int    $status_code HTTP status code. Default is 200.
	 *
	 * @return WP_REST_Response REST API response object.
	 */
	public function response_success( $data = null, string $message = '', int $status_code = 200 ): WP_REST_Response {
		if ( ! empty( $message ) ) {
			// If a message is provided, structure the response with message and data.
			$response_data = array(
				'success' => true,
				'message' => $message,
				'data'    => $data,
			);
		} else {
			// If no message, just return the data directly.
			$response_data = $data;
		}

		// Allow filtering response data.
		$response_data = apply_filters( 'wc_affiliate_rest_api_response_success', $response_data, $data, $message, $status_code );

		// Create and return the REST response.
		return new WP_REST_Response( $response_data, $status_code );
	}

	/**
	 * Creates an error REST API response.
	 *
	 * @param string|WP_Error $message     Error message or WP_Error object.
	 * @param int             $status_code HTTP status code. Default is 400.
	 * @param mixed           $data        Additional error data.
	 *
	 * @return WP_Error REST API error object.
	 */
	public function response_error( $message, int $status_code = 400, $data = null ): WP_Error {
		if ( is_wp_error( $message ) ) {
			// Allow filtering WP_Error objects.
			return apply_filters( 'wc_affiliate_rest_api_response_error', $message, $message, $status_code, $data );
		}

		$error_data = array(
			'status'      => $status_code,
			'errors_data' => $data,
		);

		// Allow filtering error data.
		$error_data = apply_filters( 'wc_affiliate_rest_api_error_data', $error_data, $message, $status_code, $data );

		$error = new WP_Error(
			'rest_error',
			$message,
			$error_data
		);

		// Allow filtering final error object.
		return apply_filters( 'wc_affiliate_rest_api_response_error', $error, $message, $status_code, $data );
	}

	/**
	 * Creates a REST API response with arbitrary data.
	 *
	 * @param mixed $data        The response data.
	 * @param int   $status_code HTTP status code. Default is 200.
	 *
	 * @return WP_REST_Response REST API response object.
	 */
	public function response( $data, int $status_code = 200 ): WP_REST_Response {
		return new WP_REST_Response( $data, $status_code );
	}

	/**
	 * Validate pagination parameters
	 *
	 * @param WP_REST_Request $request The request object.
	 *
	 * @return array Pagination parameters including page, per_page, offset, and limit
	 */
	public function get_pagination_params( WP_REST_Request $request ): array {
		$page     = max( 1, (int) $request->get_param( 'page' ) );
		$per_page = min( 100, max( 1, (int) $request->get_param( 'per_page' ) ) );
		$offset   = ( $page - 1 ) * $per_page;

		return array(
			'page'     => $page,
			'per_page' => $per_page,
			'offset'   => $offset,
			'limit'    => $per_page,
		);
	}

	/**
	 * Add pagination headers to response
	 *
	 * @param WP_REST_Response $response    The response object.
	 * @param int              $total_items Total number of items.
	 * @param int              $page        Current page number.
	 * @param int              $per_page    Number of items per page.
	 */
	public function add_pagination_headers( WP_REST_Response $response, int $total_items, int $page, int $per_page ): WP_REST_Response {
		$total_pages = ceil( $total_items / $per_page );

		$response->header( 'X-WP-Total', (int) $total_items );
		$response->header( 'X-WP-TotalPages', (int) $total_pages );

		return $response;
	}
}
