<?php
/**
 * Square webhook helpers for PMPro recurring billing.
 *
 * @package SHC4WC
 */

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

/**
 * Maps Square subscription/invoice webhook events to PMPro order + membership actions.
 */
class SHC4WC_PMPro_Webhook {

	/**
	 * @param string              $type  Square event type.
	 * @param array<string,mixed> $event Full webhook payload.
	 * @param SHC4WC_API          $api   Logger/API client.
	 * @return void
	 */
	public static function maybe_handle_event( $type, array $event, SHC4WC_API $api ) {
		if ( ! function_exists( 'pmpro_getGateway' ) || 'square_connect' !== pmpro_getGateway() ) {
			// Still handle events for historical square_connect subscriptions when gateway changed.
		}

		switch ( $type ) {
			case 'invoice.payment_succeeded':
				self::handle_invoice_payment_succeeded( $event, $api );
				break;
			case 'invoice.payment_failed':
				self::handle_invoice_payment_failed( $event, $api );
				break;
			case 'subscription.created':
				self::handle_subscription_created( $event, $api );
				break;
			case 'subscription.canceled':
			case 'subscription.deactivated':
				self::handle_subscription_canceled( $event, $api );
				break;
		}
	}

	/**
	 * @param array<string,mixed> $event Webhook payload.
	 * @param SHC4WC_API          $api   Logger.
	 * @return void
	 */
	private static function handle_invoice_payment_succeeded( array $event, SHC4WC_API $api ) {
		if ( ! function_exists( 'pmpro_handle_recurring_payment_succeeded_at_gateway' ) ) {
			return;
		}

		$order_data = self::build_order_data_from_invoice( $event );
		if ( empty( $order_data['subscription_transaction_id'] ) ) {
			return;
		}

		if ( isset( $order_data['total'] ) && (float) $order_data['total'] <= 0 ) {
			return;
		}

		$log = pmpro_handle_recurring_payment_succeeded_at_gateway( $order_data );
		$api->log( 'PMPro Square recurring payment succeeded', array( 'log' => $log, 'order_data' => $order_data ) );
	}

	/**
	 * @param array<string,mixed> $event Webhook payload.
	 * @param SHC4WC_API          $api   Logger.
	 * @return void
	 */
	private static function handle_invoice_payment_failed( array $event, SHC4WC_API $api ) {
		if ( ! function_exists( 'pmpro_handle_recurring_payment_failure_at_gateway' ) ) {
			return;
		}

		$order_data = self::build_order_data_from_invoice( $event );
		if ( empty( $order_data['subscription_transaction_id'] ) ) {
			return;
		}

		$log = pmpro_handle_recurring_payment_failure_at_gateway( $order_data );
		$api->log( 'PMPro Square recurring payment failed', array( 'log' => $log, 'order_data' => $order_data ), 'warning' );
	}

	/**
	 * @param array<string,mixed> $event Webhook payload.
	 * @param SHC4WC_API          $api   Logger.
	 * @return void
	 */
	private static function handle_subscription_created( array $event, SHC4WC_API $api ) {
		$subscription    = self::extract_subscription_object( $event );
		$subscription_id = isset( $subscription['id'] ) ? sanitize_text_field( (string) $subscription['id'] ) : '';

		if ( '' === $subscription_id ) {
			return;
		}

		$attached = self::attach_subscription_to_recent_pmpro_order( $subscription_id );
		if ( $attached ) {
			$api->log(
				'PMPro Square subscription id attached to order',
				array(
					'order_id'        => $attached,
					'subscription_id' => $subscription_id,
				)
			);
		}

		do_action( 'shc4wc_pmpro_subscription_created', $subscription );
	}

	/**
	 * @param string $subscription_id Square subscription id.
	 * @return int Attached order id or 0.
	 */
	private static function attach_subscription_to_recent_pmpro_order( $subscription_id ) {
		global $wpdb;

		$order_id = (int) $wpdb->get_var( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
			$wpdb->prepare(
				"SELECT id FROM {$wpdb->pmpro_membership_orders}
				WHERE gateway = %s
				AND status = 'success'
				AND (subscription_transaction_id IS NULL OR subscription_transaction_id = '')
				ORDER BY id DESC
				LIMIT 1",
				'square_connect'
			)
		);

		if ( $order_id <= 0 || ! class_exists( 'MemberOrder' ) ) {
			return 0;
		}

		$order = new MemberOrder( $order_id );
		if ( empty( $order->id ) ) {
			return 0;
		}

		$order->subscription_transaction_id = $subscription_id;
		$order->saveOrder();

		return (int) $order->id;
	}

	/**
	 * @param array<string,mixed> $event Webhook payload.
	 * @param SHC4WC_API          $api   Logger.
	 * @return void
	 */
	private static function handle_subscription_canceled( array $event, SHC4WC_API $api ) {
		if ( ! function_exists( 'pmpro_handle_subscription_cancellation_at_gateway' ) ) {
			return;
		}

		$subscription    = self::extract_subscription_object( $event );
		$subscription_id = isset( $subscription['id'] ) ? sanitize_text_field( (string) $subscription['id'] ) : '';
		if ( '' === $subscription_id ) {
			return;
		}

		$environment = ( isset( SHC4WC_Plugin::get_settings()['environment'] ) && 'live' === SHC4WC_Plugin::get_settings()['environment'] ) ? 'live' : 'sandbox';
		$log         = pmpro_handle_subscription_cancellation_at_gateway( $subscription_id, 'square_connect', $environment );
		$api->log( 'PMPro Square subscription canceled', array( 'log' => $log, 'subscription_id' => $subscription_id ) );
	}

	/**
	 * @param array<string,mixed> $event Webhook payload.
	 * @return array<string,mixed>
	 */
	private static function build_order_data_from_invoice( array $event ) {
		$invoice = isset( $event['data']['object']['invoice'] ) && is_array( $event['data']['object']['invoice'] )
			? $event['data']['object']['invoice']
			: ( isset( $event['data']['object'] ) && is_array( $event['data']['object'] ) ? $event['data']['object'] : array() );

		$subscription_id = ! empty( $invoice['subscription_id'] ) ? sanitize_text_field( (string) $invoice['subscription_id'] ) : '';
		$payment_id      = ! empty( $invoice['id'] ) ? sanitize_text_field( (string) $invoice['id'] ) : '';
		$total           = 0.0;

		if ( ! empty( $invoice['payment_requests'][0]['computed_amount_money']['amount'] ) ) {
			$total = ( (int) $invoice['payment_requests'][0]['computed_amount_money']['amount'] ) / 100;
		}

		$environment = ( isset( SHC4WC_Plugin::get_settings()['environment'] ) && 'live' === SHC4WC_Plugin::get_settings()['environment'] ) ? 'live' : 'sandbox';

		return array(
			'gateway'                     => 'square_connect',
			'gateway_environment'         => $environment,
			'timestamp'                   => time(),
			'subscription_transaction_id' => $subscription_id,
			'payment_transaction_id'      => $payment_id,
			'total'                       => $total,
			'subtotal'                    => $total,
			'tax'                         => 0,
			'payment_type'                => 'Square Hosted Checkout',
		);
	}

	/**
	 * @param array<string,mixed> $event Webhook payload.
	 * @return array<string,mixed>
	 */
	private static function extract_subscription_object( array $event ) {
		if ( isset( $event['data']['object']['subscription'] ) && is_array( $event['data']['object']['subscription'] ) ) {
			return $event['data']['object']['subscription'];
		}
		if ( isset( $event['data']['object'] ) && is_array( $event['data']['object'] ) ) {
			return $event['data']['object'];
		}
		return array();
	}
}
