<?php
if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

if ( ! class_exists( 'SftcyWordformPaymentPaypal' ) ) {
	class SftcyWordformPaymentPaypal {

		/**
		 * Get PayPal settings from payment config.
		 *
		 * @return array
		 */
		public static function get_settings() {
			$settings = SftcyWordformBase::wordform_settings_page_payment_config();

			return array(
				'enabled'       => isset( $settings['paypal_enabled'] ) ? sanitize_text_field( $settings['paypal_enabled'] ) : 'no',
				'mode'          => isset( $settings['paypal_mode'] ) ? sanitize_text_field( $settings['paypal_mode'] ) : 'sandbox',
				'client_id'     => isset( $settings['paypal_client_id'] ) ? trim( sanitize_text_field( $settings['paypal_client_id'] ) ) : '',
				'client_secret' => isset( $settings['paypal_client_secret'] ) ? trim( sanitize_text_field( $settings['paypal_client_secret'] ) ) : '',
				'currency'      => isset( $settings['payment_currency'] ) ? strtoupper( sanitize_text_field( $settings['payment_currency'] ) ) : 'USD',
			);
		}

		/**
		 * Create a PayPal order.
		 *
		 * @param float  $amount
		 * @param string $currency
		 * @param string $form_id
		 * @param string $form_name
		 * @return array
		 */
		public static function create_order( $amount = 0, $currency = 'USD', $form_id = '', $form_name = '' ) {
			$settings = self::get_settings();

			if ( 'yes' !== $settings['enabled'] ) {
				return array(
					'status'  => 'fail',
					'reason'  => 'PayPal is disabled.',
					'comment' => __( 'Enable PayPal in Payment settings first.', 'wordform-pro' ),
				);
			}

			if ( empty( $settings['client_id'] ) || empty( $settings['client_secret'] ) ) {
				return array(
					'status'  => 'fail',
					'reason'  => 'PayPal credentials missing.',
					'comment' => __( 'PayPal client ID or client secret is missing.', 'wordform-pro' ),
				);
			}

			$access_token = self::get_access_token();
			if ( isset( $access_token['status'] ) && 'fail' === $access_token['status'] ) {
				return $access_token;
			}

			$amount   = max( 0, (float) $amount );
			$currency = strtoupper( sanitize_text_field( $currency ) );
			if ( $amount <= 0 ) {
				return array(
					'status'  => 'fail',
					'reason'  => 'Invalid PayPal amount.',
					'comment' => __( 'Payment amount must be greater than zero.', 'wordform-pro' ),
				);
			}

			$response = wp_remote_post(
				self::get_api_base_url() . '/v2/checkout/orders',
				array(
					'timeout' => 45,
					'headers' => array(
						'Authorization'   => 'Bearer ' . $access_token['access_token'],
						'Content-Type'    => 'application/json',
						'PayPal-Request-Id' => wp_generate_uuid4(),
					),
					'body'    => wp_json_encode(
						array(
							'intent'         => 'CAPTURE',
							'purchase_units' => array(
								array(
									'custom_id' => sanitize_text_field( $form_id ),
									'description' => sprintf(
										/* translators: 1: form name, 2: form id */
										__( 'WordForm payment for %1$s (%2$s)', 'wordform-pro' ),
										sanitize_text_field( $form_name ),
										sanitize_text_field( $form_id )
									),
									'amount'    => array(
										'currency_code' => $currency,
										'value'         => number_format( $amount, 2, '.', '' ),
									),
								),
							),
						)
					),
				)
			);

			if ( is_wp_error( $response ) ) {
				return array(
					'status'  => 'fail',
					'reason'  => 'PayPal order request failed.',
					'comment' => $response->get_error_message(),
				);
			}

			$body         = json_decode( wp_remote_retrieve_body( $response ), true );
			$status_code  = (int) wp_remote_retrieve_response_code( $response );

			if ( $status_code < 200 || $status_code >= 300 || empty( $body['id'] ) ) {
				$error_message = isset( $body['message'] ) ? sanitize_text_field( $body['message'] ) : __( 'PayPal order could not be created.', 'wordform-pro' );

				return array(
					'status'  => 'fail',
					'reason'  => 'PayPal order creation failed.',
					'comment' => $error_message,
					'raw'     => $body,
				);
			}

			return array(
				'status'    => 'success',
				'orderId'   => sanitize_text_field( $body['id'] ),
				'amount'    => number_format( $amount, 2, '.', '' ),
				'currency'  => $currency,
			);
		}

		/**
		 * Capture an approved PayPal order.
		 *
		 * @param string $order_id
		 * @return array
		 */
		public static function capture_order( $order_id = '' ) {
			$order_id = sanitize_text_field( $order_id );
			if ( empty( $order_id ) ) {
				return array(
					'status'  => 'fail',
					'reason'  => 'PayPal order ID missing.',
					'comment' => __( 'Order ID is required to capture the payment.', 'wordform-pro' ),
				);
			}

			$access_token = self::get_access_token();
			if ( isset( $access_token['status'] ) && 'fail' === $access_token['status'] ) {
				return $access_token;
			}

			$response = wp_remote_post(
				self::get_api_base_url() . '/v2/checkout/orders/' . rawurlencode( $order_id ) . '/capture',
				array(
					'timeout' => 45,
					'headers' => array(
						'Authorization' => 'Bearer ' . $access_token['access_token'],
						'Content-Type'  => 'application/json',
					),
				)
			);

			if ( is_wp_error( $response ) ) {
				return array(
					'status'  => 'fail',
					'reason'  => 'PayPal capture request failed.',
					'comment' => $response->get_error_message(),
				);
			}

			$body        = json_decode( wp_remote_retrieve_body( $response ), true );
			$status_code = (int) wp_remote_retrieve_response_code( $response );

			if ( $status_code < 200 || $status_code >= 300 || empty( $body['status'] ) ) {
				$error_message = isset( $body['message'] ) ? sanitize_text_field( $body['message'] ) : __( 'PayPal order could not be captured.', 'wordform-pro' );

				return array(
					'status'  => 'fail',
					'reason'  => 'PayPal capture failed.',
					'comment' => $error_message,
					'raw'     => $body,
				);
			}

			$capture_id = '';
			$amount     = '';
			$currency   = '';
			if ( isset( $body['purchase_units'][0]['payments']['captures'][0] ) ) {
				$capture    = $body['purchase_units'][0]['payments']['captures'][0];
				$capture_id = isset( $capture['id'] ) ? sanitize_text_field( $capture['id'] ) : '';
				$amount     = isset( $capture['amount']['value'] ) ? sanitize_text_field( $capture['amount']['value'] ) : '';
				$currency   = isset( $capture['amount']['currency_code'] ) ? sanitize_text_field( $capture['amount']['currency_code'] ) : '';
			}

			return array(
				'status'    => 'success',
				'orderId'   => $order_id,
				'paypalStatus' => sanitize_text_field( $body['status'] ),
				'captureId' => $capture_id,
				'amount'    => $amount,
				'currency'  => $currency,
				'raw'       => $body,
			);
		}

		/**
		 * Fetch a PayPal OAuth access token.
		 *
		 * @return array
		 */
		public static function get_access_token() {
			$settings = self::get_settings();

			if ( empty( $settings['client_id'] ) || empty( $settings['client_secret'] ) ) {
				return array(
					'status'  => 'fail',
					'reason'  => 'PayPal credentials missing.',
					'comment' => __( 'PayPal client ID or client secret is missing.', 'wordform-pro' ),
				);
			}

			$response = wp_remote_post(
				self::get_api_base_url() . '/v1/oauth2/token',
				array(
					'timeout' => 45,
					'headers' => array(
						'Authorization' => 'Basic ' . base64_encode( $settings['client_id'] . ':' . $settings['client_secret'] ),
						'Content-Type'  => 'application/x-www-form-urlencoded',
					),
					'body'    => array(
						'grant_type' => 'client_credentials',
					),
				)
			);

			if ( is_wp_error( $response ) ) {
				return array(
					'status'  => 'fail',
					'reason'  => 'PayPal access token request failed.',
					'comment' => $response->get_error_message(),
				);
			}

			$body        = json_decode( wp_remote_retrieve_body( $response ), true );
			$status_code = (int) wp_remote_retrieve_response_code( $response );

			if ( $status_code < 200 || $status_code >= 300 || empty( $body['access_token'] ) ) {
				$error_message = isset( $body['error_description'] ) ? sanitize_text_field( $body['error_description'] ) : __( 'PayPal access token could not be created.', 'wordform-pro' );

				return array(
					'status'  => 'fail',
					'reason'  => 'PayPal access token failed.',
					'comment' => $error_message,
					'raw'     => $body,
				);
			}

			return array(
				'status'       => 'success',
				'access_token' => sanitize_text_field( $body['access_token'] ),
			);
		}

		/**
		 * Resolve sandbox or live PayPal API base URL.
		 *
		 * @return string
		 */
		public static function get_api_base_url() {
			$settings = self::get_settings();
			return ( isset( $settings['mode'] ) && 'live' === $settings['mode'] ) ? 'https://api-m.paypal.com' : 'https://api-m.sandbox.paypal.com';
		}
	}
}
