<?php

namespace PaymentPage\RestAPI;

if ( ! defined( 'ABSPATH' ) ) exit;

use WP_Error;
use WP_REST_Server;
use WP_REST_Request;
use PaymentPage\API\PaymentPage as API_PaymentPage;
use PaymentPage\PaymentGateway as InstancePaymentGateway;
use PaymentPage\PaymentGateway\Stripe as PaymentGateway_Stripe;
use PaymentPage\PaymentGateway\PayPal as PaymentGateway_PayPal;
use PaymentPage\Settings as PaymentPage_Settings;

class PaymentGateway {

	public static function register_routes() {
		register_rest_route(
			PAYMENT_PAGE_REST_API_PREFIX . '/v1',
			'/payment-gateway/connect',
			array(
				'methods'             => WP_REST_Server::READABLE,
				'callback'            => '\PaymentPage\RestAPI\PaymentGateway::connect',
				'permission_callback' => function() {
					return current_user_can( PAYMENT_PAGE_ADMIN_CAP );
				},
			)
		);

		register_rest_route(
			PAYMENT_PAGE_REST_API_PREFIX . '/v1',
			'/payment-gateway/disconnect',
			array(
				'methods'             => WP_REST_Server::CREATABLE,
				'callback'            => '\PaymentPage\RestAPI\PaymentGateway::disconnect',
				'permission_callback' => function() {
					return current_user_can( PAYMENT_PAGE_ADMIN_CAP );
				},
			)
		);

		register_rest_route(
			PAYMENT_PAGE_REST_API_PREFIX . '/v1',
			'/payment-gateway/set-mode',
			array(
				'methods'             => WP_REST_Server::CREATABLE,
				'callback'            => '\PaymentPage\RestAPI\PaymentGateway::set_mode',
				'permission_callback' => function() {
					return current_user_can( PAYMENT_PAGE_ADMIN_CAP );
				},
			)
		);

		register_rest_route(
			PAYMENT_PAGE_REST_API_PREFIX . '/v1',
			'/payment-gateway/set-payment-methods',
			array(
				'methods'             => WP_REST_Server::CREATABLE,
				'callback'            => '\PaymentPage\RestAPI\PaymentGateway::set_payment_methods',
				'permission_callback' => function() {
					return current_user_can( PAYMENT_PAGE_ADMIN_CAP );
				},
			)
		);

		register_rest_route(
			PAYMENT_PAGE_REST_API_PREFIX . '/v1',
			'/payment-gateway/save-webhook-settings',
			array(
				'methods'             => WP_REST_Server::CREATABLE,
				'callback'            => '\PaymentPage\RestAPI\PaymentGateway::save_webhook_settings',
				'permission_callback' => function() {
					return current_user_can( PAYMENT_PAGE_ADMIN_CAP );
				},
			)
		);

		register_rest_route(
			PAYMENT_PAGE_REST_API_PREFIX . '/v1',
			'/payment-gateway/connect-callback',
			array(
				'methods'             => WP_REST_Server::READABLE,
				'callback'            => '\PaymentPage\RestAPI\PaymentGateway::connect_callback',
				'permission_callback' => '__return_true',
			)
		);

		register_rest_route(
			PAYMENT_PAGE_REST_API_PREFIX . '/v1',
			'/payment-gateway/save-settings',
			array(
				'methods'             => WP_REST_Server::CREATABLE,
				'callback'            => '\PaymentPage\RestAPI\PaymentGateway::save_settings',
				'permission_callback' => function() {
					return current_user_can( PAYMENT_PAGE_ADMIN_CAP );
				},
			)
		);

		register_rest_route(
			PAYMENT_PAGE_REST_API_PREFIX . '/v1',
			'/payment-gateway/save-payment-method-settings',
			array(
				'methods'             => WP_REST_Server::CREATABLE,
				'callback'            => '\PaymentPage\RestAPI\PaymentGateway::save_payment_method_settings',
				'permission_callback' => function() {
					return current_user_can( PAYMENT_PAGE_ADMIN_CAP );
				},
			)
		);
	}

	public static function connect( WP_REST_Request $request ) {
		foreach ( array( 'is_live', 'payment_gateway' ) as $required_param ) {
			if ( ! $request->has_param( $required_param ) ) {
				return new WP_Error(
					'rest_error',
					/* translators: %s: request parameter name */
					esc_html( sprintf( __( 'Missing request param %s', 'payment-page' ), $required_param ) ),
					array(
						'status' => 400,
					)
				);
			}
		}

		if ( $request->get_param( 'payment_gateway' ) === 'stripe' ) {
			return rest_ensure_response(
				PaymentGateway_Stripe::setup_start_connection(
					array(
						'is_live' => $request->get_param( 'is_live' ),
					)
				)
			);
		}

		if ( $request->get_param( 'payment_gateway' ) === 'paypal' ) {
			return rest_ensure_response(
				PaymentGateway_PayPal::setup_start_connection(
					array(
						'is_live' => $request->get_param( 'is_live' ),
					)
				)
			);
		}

		return new WP_Error(
			'rest_error',
				/* translators: %s: payment gateway name */
			esc_html( sprintf( __( 'Invalid payment gateway %s', 'payment-page' ), $request->get_param( 'payment_gateway' ) ) ),
			array(
				'status' => 400,
			)
		);
	}

	public static function disconnect( WP_REST_Request $request ) {
		foreach ( array( 'is_live', 'payment_gateway' ) as $required_param ) {
			if ( ! $request->has_param( $required_param ) ) {
				return new WP_Error(
					'rest_error',
					/* translators: %s: request parameter name */
					esc_html( sprintf( __( 'Missing request param %s', 'payment-page' ), $required_param ) ),
					array(
						'status' => 400,
					)
				);
			}
		}

		$paymentGatewayInstance = InstancePaymentGateway::get_integration_from_settings( $request->get_param( 'payment_gateway' ) );

		if ( $paymentGatewayInstance === null ) {
			return new WP_Error(
				'rest_error',
				/* translators: %s: payment gateway name */
				esc_html( sprintf( __( 'Invalid payment gateway %s', 'payment-page' ), $request->get_param( 'payment_gateway' ) ) ),
				array(
					'status' => 400,
				)
			);
		}

		$paymentGatewayInstance->delete_settings_credentials( intval( $request->get_param( 'is_live' ) ) );

		return rest_ensure_response(
			array(
				'status' => 'ok',
			)
		);
	}

	public static function set_mode( WP_REST_Request $request ) {
		foreach ( array( 'is_live', 'payment_gateway' ) as $required_param ) {
			if ( ! $request->has_param( $required_param ) ) {
				return new WP_Error(
					'rest_error',
					/* translators: %s: request parameter name */
					esc_html( sprintf( __( 'Missing request param %s', 'payment-page' ), $required_param ) ),
					array(
						'status' => 400,
					)
				);
			}
		}

		$paymentGatewayInstance = InstancePaymentGateway::get_integration_from_settings( $request->get_param( 'payment_gateway' ) );

		if ( $paymentGatewayInstance === null ) {
			return new WP_Error(
				'rest_error',
				/* translators: %s: payment gateway name */
				esc_html( sprintf( __( 'Invalid payment gateway %s', 'payment-page' ), $request->get_param( 'payment_gateway' ) ) ),
				array(
					'status' => 400,
				)
			);
		}

		PaymentPage_Settings::instance()->update(
			array(
				$request->get_param( 'payment_gateway' ) . '_is_live' => intval( $request->get_param( 'is_live' ) ),
			)
		);

		if ( $request->get_param( 'payment_gateway' ) === 'stripe' ) {
			if ( _payment_page_stripe_payment_methods_background_setup( payment_page_setting_get( 'stripe_payment_methods' ) ) ) {
				return rest_ensure_response(
					array(
						'status'  => 'ok',
						'refresh' => 1,
					)
				);
			}
		}

		return rest_ensure_response(
			array(
				'status' => 'ok',
			)
		);
	}

	public static function set_payment_methods( WP_REST_Request $request ) {
		foreach ( array( 'payment_gateway', 'payment_methods' ) as $required_param ) {
			if ( ! $request->has_param( $required_param ) ) {
				return new WP_Error(
					'rest_error',
					/* translators: %s: request parameter name */
					esc_html( sprintf( __( 'Missing request param %s', 'payment-page' ), $required_param ) ),
					array(
						'status' => 400,
					)
				);
			}
		}

		$paymentGatewayInstance = InstancePaymentGateway::get_integration_from_settings( $request->get_param( 'payment_gateway' ) );

		if ( $paymentGatewayInstance === null ) {
			return new WP_Error(
				'rest_error',
				/* translators: %s: payment gateway name */
				esc_html( sprintf( __( 'Invalid payment gateway %s', 'payment-page' ), $request->get_param( 'payment_gateway' ) ) ),
				array(
					'status' => 400,
				)
			);
		}

		PaymentPage_Settings::instance()->update(
			array(
				$request->get_param( 'payment_gateway' ) . '_payment_methods' => $request->get_param( 'payment_methods' ),
			)
		);

		if ( $request->get_param( 'payment_gateway' ) === 'stripe' ) {
			if ( _payment_page_stripe_payment_methods_background_setup( $request->get_param( 'payment_methods' ) ) ) {
				return rest_ensure_response(
					array(
						'status'  => 'ok',
						'refresh' => 1,
					)
				);
			}
		}

		return rest_ensure_response(
			array(
				'status' => 'ok',
			)
		);
	}

	public static function save_webhook_settings( WP_REST_Request $request ) {
		foreach ( array( 'is_live', 'payment_gateway' ) as $required_param ) {
			if ( ! $request->has_param( $required_param ) ) {
				return new WP_Error(
					'rest_error',
					/* translators: %s: request parameter name */
					esc_html( sprintf( __( 'Missing request param %s', 'payment-page' ), $required_param ) ),
					array(
						'status' => 400,
					)
				);
			}
		}

		$payment_gateway = $request->get_param( 'payment_gateway' );

		$paymentGatewayInstance = InstancePaymentGateway::get_integration_from_settings( $payment_gateway );

		if ( empty( $paymentGatewayInstance ) || ! method_exists( $paymentGatewayInstance, 'get_webhook_settings_administration' ) ) {
			return new WP_Error(
				'rest_error',
				__( 'Invalid payment gateway', 'payment-page' ),
				array(
					'status' => 400,
				)
			);
		}

		$webhook_settings_administration = $paymentGatewayInstance->get_webhook_settings_administration();

		$target_items = $webhook_settings_administration[ intval( $request->get_param( 'is_live' ) ) ? 'live_fields' : 'test_fields' ];

		$settings_update_array = array();

		foreach ( $target_items as $setting_key => $setting_field_information ) {
			if ( ! $request->has_param( $setting_key ) ) {
				continue;
			}

			$settings_update_array[ $setting_key ] = sanitize_text_field( $request->get_param( $setting_key ) );
		}

		if ( ! empty( $settings_update_array ) ) {
			PaymentPage_Settings::instance()->update( $settings_update_array );
		}

		return rest_ensure_response( true );
	}

	public static function connect_callback( WP_REST_Request $request ) {
		if ( $request->has_param( 'cancel' ) ) {
			payment_page_redirect( admin_url( PAYMENT_PAGE_DEFAULT_URL_PATH ) . '#payment-gateways' );
			exit;
		}

		// (Audit F001 / sc-7142 — 1.5.0 fix + 1.5.1 REST-auth hotfix)
		//
		// Background: the previous implementation gated this endpoint with __return_true
		// and relied solely on the fact that the `credentials` param had to decrypt under
		// the site's anonymous_id. That "encryption-as-auth" model is broken (see F002
		// disposition memo), so 1.5.0 added two layers: an admin-cap check + a per-user
		// state-token transient.
		//
		// 1.5.0 BUG: the admin-cap check was written as `current_user_can()` against the
		// REST API context. WordPress's REST cookie-auth filter (`rest_cookie_check_errors`)
		// only authenticates a logged-in user if a valid `_wpnonce` is present on the REST
		// request — and Stripe's OAuth `redirect_uri` cannot carry our nonce. So even
		// admins arriving with a valid `wordpress_logged_in_*` cookie failed the gate and
		// got a 403. Every fresh Connect attempt broke.
		//
		// 1.5.1 fix: authenticate via the login cookie directly. `wp_validate_auth_cookie`
		// reads the `wordpress_logged_in_*` cookie and returns the user_id without needing
		// a nonce (that's its job — used by `wp-login.php`, admin-post, OAuth callbacks).
		// The security model is preserved end-to-end:
		//   (a) caller must present a valid WP logged-in cookie for an admin user, AND
		//   (b) that admin must have started a connect flow in the last 10 minutes
		//       (state transient, single-use, consumed on hit).
		// Neither gate is satisfied by a drive-by <img src=...> from an attacker.

		$current_user_id = wp_validate_auth_cookie( '', 'logged_in' );

		if ( ! $current_user_id || ! user_can( $current_user_id, PAYMENT_PAGE_ADMIN_CAP ) ) {
			return new WP_Error(
				'rest_error',
				__( 'Not authorized to complete the gateway connection. Please re-start the connect flow while logged in as an administrator.', 'payment-page' ),
				array(
					'status' => 403,
				)
			);
		}

		// Fold the cookie-validated user into the REST request's auth context so
		// downstream code that calls `wp_get_current_user()` / `get_current_user_id()`
		// sees the same admin (the state-check below + AdminController helpers used
		// by the webhook auto-provisioner).
		wp_set_current_user( $current_user_id );

		// State token round-trip: until the proxy is updated to echo `state` back on
		// callback, we rely on the per-user transient presence check below.
		$callback_state = (string) ( $request->get_param( 'state' ) ?: '' );

		if ( $request->get_param( 'payment-gateway' ) === 'stripe' ) {
			if ( ! PaymentGateway_Stripe::verify_connect_state( $current_user_id, $callback_state ) ) {
				return new WP_Error(
					'rest_error',
					__( 'Connect flow expired or not initiated by this user. Please re-start the connect flow from the admin dashboard.', 'payment-page' ),
					array(
						'status' => 400,
					)
				);
			}
		}

		foreach ( array( 'payment-gateway', 'credentials' ) as $required_param ) {
			if ( ! $request->has_param( $required_param ) ) {
				return new WP_Error(
					'rest_error',
					/* translators: %s: request parameter name */
					esc_html( sprintf( __( 'Missing request param %s', 'payment-page' ), $required_param ) ),
					array(
						'status' => 400,
					)
				);
			}
		}

		$credentials = API_PaymentPage::instance()->decode_response_data( $request->get_param( 'credentials' ) );

		if ( ! is_array( $credentials ) ) {
			return new WP_Error(
				'rest_error',
				__( 'Invalid Credentials...', 'payment-page' ),
				array(
					'status' => 400,
				)
			);
		}

		if ( $request->get_param( 'payment-gateway' ) === 'stripe' ) {
			if ( ! PaymentGateway_Stripe::save_master_credentials_response( $credentials ) ) {
				return new WP_Error(
					'rest_error',
					__( 'Invalid Credentials...', 'payment-page' ),
					array(
						'status' => 400,
					)
				);
			}
		}

		payment_page_redirect( admin_url( PAYMENT_PAGE_DEFAULT_URL_PATH ) . '#payment-gateways' );
		exit;
	}

	public static function save_settings( WP_REST_Request $request ) {
		foreach ( array( 'is_live', 'payment_gateway' ) as $required_param ) {
			if ( ! $request->has_param( $required_param ) ) {
				return new WP_Error(
					'rest_error',
					/* translators: %s: request parameter name */
					esc_html( sprintf( __( 'Missing request param %s', 'payment-page' ), $required_param ) ),
					array(
						'status' => 400,
					)
				);
			}
		}

		if ( $request->get_param( 'payment_gateway' ) === 'paypal' ) {
			if ( ! PaymentGateway_PayPal::save_master_credentials_response( $request->get_params() ) ) {
				return new WP_Error(
					'rest_error',
					__( 'Invalid Credentials...', 'payment-page' ),
					array(
						'status' => 400,
					)
				);
			}

			return rest_ensure_response( true );
		}

		return new WP_Error(
			'rest_error',
			__( 'Invalid payment gateway', 'payment-page' ),
			array(
				'status' => 400,
			)
		);
	}

	public static function save_payment_method_settings( WP_REST_Request $request ) {
		foreach ( array( 'is_live', 'payment_gateway', 'payment_method' ) as $required_param ) {
			if ( ! $request->has_param( $required_param ) ) {
				return new WP_Error(
					'rest_error',
					/* translators: %s: request parameter name */
					esc_html( sprintf( __( 'Missing request param %s', 'payment-page' ), $required_param ) ),
					array(
						'status' => 400,
					)
				);
			}
		}

		$payment_gateway = $request->get_param( 'payment_gateway' );
		$payment_method  = $request->get_param( 'payment_method' );

		$paymentGatewayInstance = InstancePaymentGateway::get_integration_from_settings( $payment_gateway );

		if ( empty( $paymentGatewayInstance ) ) {
			return new WP_Error(
				'rest_error',
				__( 'Invalid payment gateway', 'payment-page' ),
				array(
					'status' => 400,
				)
			);
		}

		$payment_methods_administration = $paymentGatewayInstance->get_payment_methods_administration();

		if ( ! isset( $payment_methods_administration[ $payment_method ] )
		|| ! isset( $payment_methods_administration[ $payment_method ]['settings'] ) ) {
			return new WP_Error(
				'rest_error',
				__( 'Invalid payment method', 'payment-page' ),
				array(
					'status' => 400,
				)
			);
		}

		$settings_update_array = array();

		foreach ( $payment_methods_administration[ $payment_method ]['settings'] as $settings_group_key => $settings_group_map ) {
			$target_items = $settings_group_map[ intval( $request->get_param( 'is_live' ) ) ? 'live_fields' : 'test_fields' ];

			foreach ( $target_items as $setting_key => $setting_field_information ) {
				if ( ! $request->has_param( $setting_key ) ) {
					continue;
				}

				$settings_update_array[ $setting_key ] = sanitize_text_field( $request->get_param( $setting_key ) );
			}
		}

		if ( ! empty( $settings_update_array ) ) {
			PaymentPage_Settings::instance()->update( $settings_update_array );
		}

		return rest_ensure_response( true );
	}

}
