<?php
/**
 * PeachPay ConvesioPay Google Pay Gateway
 *
 * @package PeachPay
 */

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

require_once PEACHPAY_ABSPATH . 'core/abstract/class-peachpay-payment-gateway.php';

/**
 * ConvesioPay Google Pay Gateway
 */
class PeachPay_ConvesioPay_GooglePay_Gateway extends PeachPay_Payment_Gateway {

	use PeachPay_ConvesioPay_Subscription_Renewal_Trait;
	/**
	 * Track if gateway was properly initialized
	 *
	 * @var bool
	 */
	private $initialized = false;

	/**
	 * Gateway settings.
	 *
	 * @var array
	 */
	public $settings = array();

	/**
	 * Constructor.
	 */
	public function __construct() {
		$this->id                 = 'peachpay_convesiopay_googlepay';
		$this->title              = 'Google Pay';
		$this->description        = sprintf( __( 'After selecting %s a prompt will appear to complete your payment.', 'peachpay-for-woocommerce' ), 'Google Pay' );
		$this->method_title       = sprintf( __( '%s via ConvesioPay (PeachPay)', 'peachpay-for-woocommerce' ), 'Google Pay' );
		$this->method_description = 'Accept Google Pay payments through ConvesioPay';
		$this->has_fields         = true;
		$this->supports           = array(
			'products',
			'refunds',
			'blocks',
			'subscriptions',
			'multiple_subscriptions',
			'subscription_cancellation',
			'subscription_suspension',
			'subscription_reactivation',
			'subscription_amount_changes',
			'subscription_date_changes',
			'subscription_payment_method_change_customer',
		);
		$this->icon               = '';
		$this->icons              = array(
			'full'  => array(
				'white' => PeachPay::get_asset_url( 'img/marks/googlepay-full.svg' ),
			),
			'small' => array(
				'white' => PeachPay::get_asset_url( 'img/marks/googlepay-small-white.svg' ),
			),
		);
		$this->payment_provider       = 'ConvesioPay';
		$this->payment_method_family  = __( 'Digital wallet', 'peachpay-for-woocommerce' );
		$this->currencies             = array( 'USD' );
		$this->min_amount             = 0.50;

		parent::__construct();

		if ( ! isset( $this->settings['enabled'] ) ) {
			$this->enabled = 'yes';
		}

		add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) );
		add_action( 'woocommerce_settings_' . $this->id, array( $this, 'add_information_block' ) );

		// Subscription renewal support.
		$this->register_subscription_renewal_hook();

		$this->init_form_fields();
		$this->initialized = true;
	}

	/**
	 * Initialize gateway form fields.
	 */
	public function init_form_fields() {
		parent::init_form_fields();

		$googlepay_fields = array(
			'googlepay_info' => array(
				'title'       => 'Configuration',
				'type'        => 'title',
				'description' => '<div style="background: #f8f9fa; border-left: 4px solid #0073aa; padding: 15px; margin: 10px 0; border-radius: 4px;">
					<p style="margin: 0 0 8px 0;"><strong>Step 1:</strong> Enable <code>Google Pay</code> on the ConvesioPay Checkout API payment methods page.</p>
					<p style="margin: 0 0 8px 0;"><strong>Step 2:</strong> Register every checkout domain you want to use in the <code>Google Pay Domains</code> table in the ConvesioPay dashboard.</p>
					<p style="margin: 0 0 8px 0;"><strong>Step 3:</strong> Make sure your WooCommerce checkout domain matches the registered production or sandbox domain exactly.</p>
					<hr style="margin: 15px 0; border: none; border-top: 1px solid #ddd;">
					<p style="margin: 0; font-size: 13px; color: #666;"><em>If Google Pay does not appear, first verify dashboard enablement and registered domains.</em></p>
				</div>',
			),
		);

		$this->form_fields = array_merge( $googlepay_fields, $this->form_fields );

		if ( isset( $this->form_fields['active_locations'] ) ) {
			$this->form_fields['active_locations']['options']     = array(
				'default'               => __( 'Native checkout and PeachPay Express Checkout', 'peachpay-for-woocommerce' ),
				'checkout_page_only'    => __( 'Native checkout only', 'peachpay-for-woocommerce' ),
				'express_checkout_only' => __( 'PeachPay Express Checkout only', 'peachpay-for-woocommerce' ),
			);
			$this->form_fields['active_locations']['description'] = __( 'Native checkout means the standard WooCommerce classic/block checkout payment method area. This setting does not control ConvesioPay Accelerated Checkout buttons.', 'peachpay-for-woocommerce' );
		}
	}

	/**
	 * Get formatted minimum charge.
	 *
	 * @return string
	 */
	public function get_minimum_charge() {
		$min_charge = parent::get_minimum_charge();
		return number_format( (float) $min_charge, 2, '.', '' );
	}

	/**
	 * Gets the maximum charge.
	 *
	 * @return float
	 */
	public function get_maximum_charge() {
		return INF;
	}

	/**
	 * Check if the gateway is available for use.
	 *
	 * @param bool $skip_cart_check Whether to skip cart check.
	 * @return bool
	 */
	public function is_available( $skip_cart_check = false ) {
		return false;
	}

	/**
	 * Get ConvesioPay configuration.
	 *
	 * @return array
	 */
	private function get_convesiopay_config() {
		return PeachPay_ConvesioPay_Integration::config();
	}

	/**
	 * Process the payment using token-based Google Pay flow.
	 *
	 * @param int $order_id Order ID.
	 * @return array
	 * @throws Exception When the Google Pay token is missing.
	 */
	public function process_payment( $order_id ) {
		peachpay_log( 'info', 'ConvesioPay Google Pay: Starting process_payment for order ' . $order_id );
		$order = wc_get_order( $order_id );
		peachpay_log( 'info', 'ConvesioPay Google Pay: Order found for order ' . $order_id );
		if ( ! $order ) {
			peachpay_log( 'error', 'ConvesioPay Google Pay: Order not found for order ' . $order_id );
			return array(
				'result'  => 'failure',
				'message' => __( 'Order not found.', 'peachpay-for-woocommerce' ),
			);
		}
		peachpay_log( 'info', 'ConvesioPay Google Pay: Order found for order ' . $order_id );
		$payment_token = $this->get_payment_token_from_request();

		peachpay_log(
			'info',
			'ConvesioPay Google Pay: Starting process_payment for order ' . $order->get_order_number() . ' | ' . wp_json_encode(
				array(
					'has_token'             => ! empty( $payment_token ),
					'token_length'          => strlen( (string) $payment_token ),
					'token_prefix'          => substr( (string) $payment_token, 0, 8 ),
					'posted_amount'         => isset( $_POST['googlepay_amount'] ) ? sanitize_text_field( wp_unslash( $_POST['googlepay_amount'] ) ) : '',
					'posted_currency'       => isset( $_POST['googlepay_currency'] ) ? sanitize_text_field( wp_unslash( $_POST['googlepay_currency'] ) ) : '',
					'posted_payment_method' => isset( $_POST['payment_method'] ) ? sanitize_text_field( wp_unslash( $_POST['payment_method'] ) ) : '',
				)
			)
		);

		if ( empty( $payment_token ) ) {
			throw new Exception( __( 'Google Pay payment token is missing. Please try again.', 'peachpay-for-woocommerce' ) );
		}

		parent::process_payment( $order_id );

		try {
			$config = $this->get_convesiopay_config();

			if ( empty( $config ) || empty( $config['secret_key'] ) ) {
				throw new Exception( __( 'ConvesioPay is not properly configured.', 'peachpay-for-woocommerce' ) );
			}

			$order_amount       = $order->get_total();
			$order_amount_cents = (int) round( (float) $order_amount * 100 );

			$billing_address = array(
				'houseNumberOrName' => $order->get_billing_address_1(),
				'street'            => $order->get_billing_address_2(),
				'city'              => $order->get_billing_city(),
				'stateOrProvince'   => $order->get_billing_state(),
				'postalCode'        => $order->get_billing_postcode(),
				'country'           => $order->get_billing_country(),
			);

			$shipping_address = array(
				'houseNumberOrName' => $order->get_shipping_address_1(),
				'street'            => $order->get_shipping_address_2(),
				'city'              => $order->get_shipping_city(),
				'stateOrProvince'   => $order->get_shipping_state(),
				'postalCode'        => $order->get_shipping_postcode(),
				'country'           => $order->get_shipping_country(),
			);

			$line_items           = $this->get_line_items( $order );
			$line_items_sum_cents = 0;
			foreach ( $line_items as $line_item ) {
				$line_items_sum_cents += isset( $line_item['amountIncludingTax'] ) ? (int) $line_item['amountIncludingTax'] : 0;
			}

			$frontend_amount       = isset( $_POST['googlepay_amount'] ) ? sanitize_text_field( wp_unslash( $_POST['googlepay_amount'] ) ) : '';
			$frontend_amount_cents = $this->parse_amount_to_cents( $frontend_amount );
			$request_amount_cents  = $order_amount_cents;

			if ( null !== $frontend_amount_cents && $frontend_amount_cents > 0 ) {
				$amount_diff_cents = abs( $frontend_amount_cents - $order_amount_cents );
				if ( $amount_diff_cents > 1 ) {
					peachpay_log( 'warning', 'ConvesioPay: Google Pay frontend amount differs from order total for order ' . $order->get_order_number() . ' (order_cents: ' . $order_amount_cents . ', frontend_cents: ' . $frontend_amount_cents . '). Rejecting so user re-authorizes.' );
					throw new Exception( __( 'Order total has changed. Please confirm the payment amount and try again.', 'peachpay-for-woocommerce' ) );
				}
			}

			$line_items_diff_cents = $request_amount_cents - $line_items_sum_cents;
			if ( 0 !== $line_items_diff_cents ) {
				if ( $line_items_diff_cents > 0 ) {
					$line_items[] = array(
						'description'        => __( 'Tax/rounding adjustment', 'peachpay-for-woocommerce' ),
						'quantity'           => 1,
						'amountIncludingTax' => $line_items_diff_cents,
					);
				} elseif ( ! empty( $line_items ) && isset( $line_items[0]['amountIncludingTax'] ) && ( (int) $line_items[0]['amountIncludingTax'] + $line_items_diff_cents ) > 0 ) {
					$line_items[0]['amountIncludingTax'] = (int) $line_items[0]['amountIncludingTax'] + $line_items_diff_cents;
				}
			}

			$payment_data = array(
				'integration'        => $config['integration_name'] ?? 'PeachPay',
				'returnUrl'          => $this->get_return_url( $order ),
				'paymentToken'       => $payment_token,
				'orderNumber'        => $order->get_order_number(),
				'amount'             => $request_amount_cents,
				'currency'           => 'USD',
				'email'              => $order->get_billing_email(),
				'name'               => $order->get_billing_first_name() . ' ' . $order->get_billing_last_name(),
				'storePaymentMethod' => true,
				'lineItems'          => $line_items,
			);

			if ( peachpay_convesiopay_is_complete_address( $billing_address ) ) {
				$payment_data['billingAddress'] = $billing_address;
			}

			if ( peachpay_convesiopay_is_complete_address( $shipping_address ) ) {
				$payment_data['shippingAddress'] = $shipping_address;
			}

			$api_url = $config['api_url'] . '/payments';

			if ( empty( $config['secret_key'] ) || trim( $config['secret_key'] ) === '' ) {
				throw new Exception( __( 'ConvesioPay secret key is not configured. Please check your settings.', 'peachpay-for-woocommerce' ) );
			}

			$request_body = wp_json_encode( $payment_data );
			$response     = wp_remote_post(
				$api_url,
				array(
					'headers' => array(
						'Authorization' => $config['secret_key'],
						'Content-Type'  => 'application/json',
					),
					'body'    => $request_body,
					'timeout' => 30,
				)
			);

			if ( is_wp_error( $response ) ) {
				peachpay_log( 'error', 'ConvesioPay: Google Pay payment network error - ' . $response->get_error_message() . ' (order ' . $order->get_order_number() . ')' );
				throw new Exception( 'Network error: ' . $response->get_error_message() );
			}

			$response_code = wp_remote_retrieve_response_code( $response );
			$response_body = wp_remote_retrieve_body( $response );
			$response_data = json_decode( $response_body, true );

			peachpay_log(
				'info',
				'ConvesioPay Google Pay: API response for order ' . $order->get_order_number() . ' | ' . wp_json_encode(
					array(
						'response_code' => $response_code,
						'response_data' => $response_data,
						'response_body' => $response_body,
					)
				)
			);

			if ( $response_code !== 200 ) {
				$error_message = 'ConvesioPay API error (HTTP ' . $response_code . ')';
				if ( is_array( $response_data ) ) {
					if ( isset( $response_data['message'] ) ) {
						$error_message .= ': ' . $response_data['message'];
					} elseif ( isset( $response_data['body']['message'] ) ) {
						$error_message .= ': ' . $response_data['body']['message'];
					}
				}
				throw new Exception( $error_message );
			}

			$status     = $response_data['status'] ?? '';
			$payment_id = $response_data['id'] ?? '';

			if ( empty( $status ) || empty( $payment_id ) ) {
				peachpay_log( 'error', 'ConvesioPay: Google Pay payment invalid response - missing status or id (order ' . $order->get_order_number() . ')' );
				throw new Exception( 'Invalid response from ConvesioPay' );
			}

			$manual_capture_mode = $response_data['manualPaymentCapture'] ?? false;

			$order->update_meta_data( '_convesiopay_payment_id', $payment_id );
			$order->update_meta_data( '_convesiopay_original_payment_id', $payment_id );
			$order->update_meta_data( '_convesiopay_manual_capture_mode', $manual_capture_mode ? 'yes' : 'no' );
			$order->set_transaction_id( $payment_id );

			$payment_url = peachpay_convesiopay_dashboard_url() . '/payments/' . $payment_id;

			if ( in_array( $status, array( 'Succeeded', 'Pending', 'Refused', 'Blocked' ), true ) ) {
				if ( $status === 'Succeeded' ) {
					$order->add_order_note(
						sprintf(
							__( 'Google Pay payment succeeded via ConvesioPay. Payment ID: %s | <a href="%s" target="_blank">View Payment</a>', 'peachpay-for-woocommerce' ),
							$payment_id,
							$payment_url
						)
					);
					$order->update_meta_data( '_convesiopay_payment_status', 'captured' );
					$order->payment_complete( $payment_id );
				} elseif ( $status === 'Pending' ) {
					if ( $manual_capture_mode ) {
						$order->add_order_note(
							sprintf(
								__( 'Google Pay payment authorized and ready for manual capture. Payment ID: %s | <a href="%s" target="_blank">View Payment</a>', 'peachpay-for-woocommerce' ),
								$payment_id,
								$payment_url
							)
						);
						$order->update_meta_data( '_convesiopay_payment_status', 'authorized' );
						$order->update_status( 'pending', __( 'Payment authorized via ConvesioPay. Ready for manual capture.', 'peachpay-for-woocommerce' ) );
					} else {
						$order->add_order_note(
							sprintf(
								__( 'Google Pay payment authorized and awaiting confirmation. Payment ID: %s | <a href="%s" target="_blank">View Payment</a>', 'peachpay-for-woocommerce' ),
								$payment_id,
								$payment_url
							)
						);
						$order->update_meta_data( '_convesiopay_payment_status', 'pending_capture' );
						$order->update_status( 'pending', __( 'Payment authorized via ConvesioPay. Awaiting confirmation.', 'peachpay-for-woocommerce' ) );
					}
				} elseif ( $status === 'Refused' || $status === 'Blocked' ) {
					$order->add_order_note(
						sprintf(
							__( 'Google Pay payment refused/blocked. Payment ID: %s | <a href="%s" target="_blank">View Payment</a>', 'peachpay-for-woocommerce' ),
							$payment_id,
							$payment_url
						)
					);
					$order->update_status( 'failed', __( 'Google Pay payment refused or blocked.', 'peachpay-for-woocommerce' ) );
				}

				$this->set_peachpay_order_details( $order );
				$order->save();

				return array(
					'result'   => 'success',
					'redirect' => $this->get_return_url( $order ),
				);
			}

			throw new Exception( 'Payment failed with status: ' . $status );
		} catch ( Exception $e ) {
			peachpay_log( 'error', 'ConvesioPay: Google Pay payment exception - ' . $e->getMessage() . ' (order ' . $order->get_order_number() . ')' );
			peachpay_log(
				'error',
				'ConvesioPay Google Pay: Failure context for order ' . $order->get_order_number() . ' | ' . wp_json_encode(
					array(
						'posted_amount'   => isset( $_POST['googlepay_amount'] ) ? sanitize_text_field( wp_unslash( $_POST['googlepay_amount'] ) ) : '',
						'posted_currency' => isset( $_POST['googlepay_currency'] ) ? sanitize_text_field( wp_unslash( $_POST['googlepay_currency'] ) ) : '',
						'order_total'     => $order->get_total(),
						'order_currency'  => $order->get_currency(),
					)
				)
			);
			$order->add_order_note(
				sprintf(
					__( 'Google Pay payment failed: %s', 'peachpay-for-woocommerce' ),
					$e->getMessage()
				)
			);
			wc_add_notice( __( 'Google Pay payment failed: ', 'peachpay-for-woocommerce' ) . $e->getMessage(), 'error' );

			return array(
				'result'   => 'failure',
				'redirect' => '',
			);
		}
	}

	/**
	 * Get payment token from request.
	 *
	 * @return string
	 */
	private function get_payment_token_from_request() {
		$payment_token = '';

		if ( isset( $_POST['convesiopay_payment_token'] ) && ! empty( $_POST['convesiopay_payment_token'] ) ) {
			$payment_token_raw = $_POST['convesiopay_payment_token'];
			if ( strpos( $payment_token_raw, ' ' ) === false && strlen( trim( $payment_token_raw ) ) >= 20 ) {
				return sanitize_text_field( $payment_token_raw );
			}
		}

		if ( empty( $payment_token ) && function_exists( 'wc_get_container' ) ) {
			try {
				$container = wc_get_container();
				if ( $container->has( \Automattic\WooCommerce\StoreApi\Schemas\CheckoutSchema::class ) ) {
					$checkout_schema = $container->get( \Automattic\WooCommerce\StoreApi\Schemas\CheckoutSchema::class );
					$request_data    = $checkout_schema->get_request_data();
					if ( isset( $request_data['payment_data']['convesiopay_payment_token'] ) ) {
						return sanitize_text_field( $request_data['payment_data']['convesiopay_payment_token'] );
					}
				}
			} catch ( Exception $e ) {
			}
		}

		if ( isset( $_POST['payment_method'] ) && $_POST['payment_method'] === 'peachpay_convesiopay_googlepay' && isset( $_POST['payment_method_data'] ) ) {
			$payment_method_data = $_POST['payment_method_data'];
			if ( is_string( $payment_method_data ) ) {
				$decoded = json_decode( stripslashes( $payment_method_data ), true );
				if ( $decoded && isset( $decoded['convesiopay_payment_token'] ) ) {
					return sanitize_text_field( $decoded['convesiopay_payment_token'] );
				}
			} elseif ( is_array( $payment_method_data ) && isset( $payment_method_data['convesiopay_payment_token'] ) ) {
				return sanitize_text_field( $payment_method_data['convesiopay_payment_token'] );
			}
		}

		return $payment_token;
	}

	/**
	 * Get transaction URL for viewing payment in ConvesioPay dashboard.
	 *
	 * @param WC_Order $order Order object.
	 * @return string
	 */
	public function get_transaction_url( $order ) {
		$payment_id = $order->get_meta( '_convesiopay_payment_id' );
		if ( empty( $payment_id ) ) {
			$payment_id = $order->get_transaction_id();
		}

		if ( ! empty( $payment_id ) ) {
			$this->view_transaction_url = peachpay_convesiopay_dashboard_url() . '/payments/%s';
			return parent::get_transaction_url( $order );
		}

		return '';
	}

	/**
	 * Get gateway icon with size and style options.
	 *
	 * @param bool   $flex Whether to use flex display.
	 * @param string $size Icon size.
	 * @param string $background Icon style.
	 * @return string
	 */
	public function get_icon( $flex = false, $size = 'full', $background = 'color' ) {
		if ( isset( $this->icons[ $size ][ $background ] ) ) {
			return '<img src="' . esc_url( $this->icons[ $size ][ $background ] ) . '" alt="' . esc_attr( $this->get_title() ) . '" class="peachpay-payment-method-icon peachpay-payment-method-icon-' . esc_attr( $size ) . '">';
		}

		foreach ( $this->icons as $size_key => $styles ) {
			foreach ( $styles as $url ) {
				return '<img src="' . esc_url( $url ) . '" alt="' . esc_attr( $this->get_title() ) . '" class="peachpay-payment-method-icon peachpay-payment-method-icon-' . esc_attr( $size_key ) . '">';
			}
		}

		return '';
	}

	/**
	 * Add information block after the settings form.
	 */
	public function add_information_block() {
		echo '<div style="background: #f8f9fa; border-left: 4px solid #0073aa; padding: 15px; margin: 20px 0; border-radius: 4px;">
			<h4 style="margin: 0 0 10px 0; color: #0073aa;">Google Pay Integration Details</h4>
			<p style="margin: 0 0 8px 0;"><strong>Payment Method:</strong> Google Pay via ConvesioPay</p>
			<p style="margin: 0 0 8px 0;"><strong>Supported Devices:</strong> Compatible Android devices and supported browsers</p>
			<p style="margin: 0 0 8px 0;"><strong>Requirements:</strong> Google Pay enabled in ConvesioPay and your checkout domain registered</p>
			<p style="margin: 0; font-size: 13px; color: #666;"><em>Google Pay will only appear when both the browser/device and your ConvesioPay dashboard configuration are eligible.</em></p>
		</div>';
	}

	/**
	 * Check if gateway is initialized.
	 *
	 * @return bool
	 */
	public function is_initialized() {
		return $this->initialized;
	}

	/**
	 * Build line items for ConvesioPay payload.
	 *
	 * @param WC_Order $order Order object.
	 * @return array
	 */
	private function get_line_items( $order ) {
		$line_items = array();

		foreach ( $order->get_items() as $item ) {
			$line_items[] = array(
				'description'        => $item->get_name(),
				'quantity'           => $item->get_quantity(),
				'amountIncludingTax' => (int) round( $item->get_total() * 100 ) + (int) round( $item->get_total_tax() * 100 ),
			);
		}

		$shipping_total = $order->get_shipping_total();
		$shipping_tax   = $order->get_shipping_tax();
		if ( $shipping_total > 0 ) {
			$line_items[] = array(
				'description'        => __( 'Shipping', 'peachpay-for-woocommerce' ),
				'quantity'           => 1,
				'amountIncludingTax' => (int) round( $shipping_total * 100 ) + (int) round( $shipping_tax * 100 ),
			);
		}

		foreach ( $order->get_fees() as $fee ) {
			$line_items[] = array(
				'description'        => $fee->get_name(),
				'quantity'           => 1,
				'amountIncludingTax' => (int) round( $fee->get_total() * 100 ) + (int) round( $fee->get_total_tax() * 100 ),
			);
		}

		return $line_items;
	}

	/**
	 * Parse posted amount into integer cents.
	 *
	 * @param string $amount_raw Raw posted amount.
	 * @return int|null
	 */
	private function parse_amount_to_cents( $amount_raw ) {
		if ( null === $amount_raw || '' === trim( (string) $amount_raw ) ) {
			return null;
		}

		$normalized = preg_replace( '/[^\d\.]/', '', (string) $amount_raw );
		if ( '' === $normalized ) {
			return null;
		}

		if ( preg_match( '/^\d+$/', $normalized ) ) {
			return (int) $normalized;
		}

		if ( is_numeric( $normalized ) ) {
			return (int) round( (float) $normalized * 100 );
		}

		return null;
	}

	/**
	 * Store PeachPay details on the order.
	 *
	 * @param WC_Order $order Order object.
	 */
	private function set_peachpay_order_details( $order ) {
		$peachpay_details = array(
			'peachpay_mode'          => peachpay_is_test_mode() ? 'test' : 'live',
			'convesiopay_mode'       => peachpay_is_test_mode() ? 'test' : 'live',
			'service_fee_percentage' => PeachPay::service_fee_enabled() ? PeachPay::service_fee_percentage() : 0,
		);

		foreach ( $peachpay_details as $key => $value ) {
			$order->update_meta_data( '_peachpay_' . $key, $value );
		}
	}
}
