<?php
/**
 * Checkout REST endpoint.
 *
 * @package WPDudeProducts
 */

declare(strict_types=1);

namespace WPDude\Products\REST;

use WPDude\Products\Checkout\Checkout_Service;
use WPDude\Products\Settings\Settings;
use WP_REST_Request;
use WP_REST_Response;

/**
 * POST /checkout
 */
final class Checkout_Controller {

	/**
	 * Register routes.
	 */
	public function register_routes(): void {
		register_rest_route(
			REST_Loader::NAMESPACE,
			'/checkout',
			array(
				'methods'             => 'POST',
				'callback'            => array( $this, 'create' ),
				'permission_callback' => array( $this, 'permissions' ),
				'args'                => array(
					'product_id' => array(
						'required'          => true,
						'type'              => 'integer',
						'sanitize_callback' => 'absint',
					),
					'qty'        => array(
						'required'          => false,
						'type'              => 'integer',
						'sanitize_callback' => 'absint',
						'default'           => 1,
					),
					'options'    => array(
						'required' => false,
						'type'     => 'object',
					),
					'nonce'      => array(
						'required' => true,
						'type'     => 'string',
					),
					'return_url' => array(
						'required'          => false,
						'type'              => 'string',
						'sanitize_callback' => 'esc_url_raw',
					),
				),
			)
		);
	}

	/**
	 * Public endpoint with nonce + rate limit.
	 *
	 * @return true|\WP_Error
	 */
	public function permissions( WP_REST_Request $request ) {
		$nonce = (string) $request->get_param( 'nonce' );
		if ( '' === $nonce ) {
			$json = $request->get_json_params();
			if ( is_array( $json ) && isset( $json['nonce'] ) ) {
				$nonce = (string) $json['nonce'];
			}
		}
		if ( '' === $nonce || ! wp_verify_nonce( $nonce, 'wpdude_dc_checkout' ) ) {
			return new \WP_Error(
				'wpdude_dc_invalid_nonce',
				__( 'This checkout session expired. Please refresh the page and try again.', 'dude-commerce' ),
				array( 'status' => 403 )
			);
		}
		if ( $this->rate_limited() ) {
			return new \WP_Error(
				'wpdude_dc_rate_limited',
				__( 'Too many checkout attempts. Please wait and try again.', 'dude-commerce' ),
				array( 'status' => 429 )
			);
		}
		return true;
	}

	/**
	 * Start checkout.
	 *
	 * @return WP_REST_Response|\WP_Error
	 */
	public function create( WP_REST_Request $request ) {
		$product_id = (int) $request->get_param( 'product_id' );
		$qty        = max( 1, (int) $request->get_param( 'qty' ) );
		$return_url = (string) $request->get_param( 'return_url' );
		if ( '' === $return_url ) {
			$return_url = wp_get_referer() ? (string) wp_get_referer() : home_url( '/' );
		}

		$options_raw = $request->get_param( 'options' );
		$options     = array();
		if ( is_array( $options_raw ) ) {
			foreach ( $options_raw as $name => $value ) {
				$options[ sanitize_text_field( (string) $name ) ] = sanitize_text_field( (string) $value );
			}
		}

		$result = ( new Checkout_Service() )->start( $product_id, $qty, $options, $return_url );
		if ( is_wp_error( $result ) ) {
			$status = (int) ( $result->get_error_data()['status'] ?? 400 );
			return new \WP_Error( $result->get_error_code(), $result->get_error_message(), array( 'status' => $status ) );
		}

		return new WP_REST_Response( $result, 200 );
	}

	/**
	 * Simple IP rate limit.
	 */
	private function rate_limited(): bool {
		$ip  = isset( $_SERVER['REMOTE_ADDR'] ) ? sanitize_text_field( wp_unslash( (string) $_SERVER['REMOTE_ADDR'] ) ) : 'unknown';
		$key = 'wpdude_dc_checkout_rl_' . md5( $ip );
		$max = Settings::is_test_mode() ? 200 : 20;
		$hits = (int) get_transient( $key );
		if ( $hits >= $max ) {
			return true;
		}
		set_transient( $key, $hits + 1, 10 * MINUTE_IN_SECONDS );
		return false;
	}
}
