<?php
/**
 * Fluent Forms admin refunds for Payments Square Connect.
 *
 * @package SHC4WC
 */

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

class SHC4WC_FluentForms_Refunds {
	/** @var self|null */
	private static $instance = null;

	public static function instance() {
		if ( null === self::$instance ) {
			self::$instance = new self();
		}
		return self::$instance;
	}

	private function __construct() {
		add_action( 'wp_ajax_fluentform_handle_payment_ajax_endpoint', array( $this, 'maybe_process_square_refund' ), 9 );
	}

	/**
	 * Call Square Refunds API before Fluent Forms records a manual refund.
	 */
	public function maybe_process_square_refund() {
		if ( ! class_exists( '\FluentForm\App\Models\Transaction' ) || ! function_exists( 'wpFluentForm' ) ) {
			return;
		}

		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		$route = isset( $_REQUEST['route'] ) ? sanitize_text_field( wp_unslash( (string) $_REQUEST['route'] ) ) : '';
		if ( 'update_transaction' !== $route ) {
			return;
		}

		$request         = wpFluentForm()->request;
		$transaction_data = $request->get( 'transaction', array() );
		if ( ! is_array( $transaction_data ) ) {
			return;
		}

		$transaction_id = isset( $transaction_data['id'] ) ? (int) $transaction_data['id'] : 0;
		if ( $transaction_id <= 0 ) {
			return;
		}

		$old_transaction = \FluentForm\App\Models\Transaction::find( $transaction_id );
		if ( ! $old_transaction || SHC4WC_FluentForms::GATEWAY_KEY !== $old_transaction->payment_method ) {
			return;
		}

		$new_status = isset( $transaction_data['status'] ) ? sanitize_text_field( (string) $transaction_data['status'] ) : '';
		$changing   = $old_transaction->status !== $new_status;
		$is_refund  = in_array( $new_status, array( 'refunded', 'partial-refunded', 'partially-refunded' ), true );

		if ( ! $changing || ! $is_refund ) {
			return;
		}

		if ( ! class_exists( '\FluentForm\App\Modules\Acl\Acl' ) ) {
			return;
		}

		$form_id = (int) $old_transaction->form_id;
		\FluentForm\App\Modules\Acl\Acl::verify( 'fluentform_forms_manager', $form_id );

		$refund_amount_cents = 0;
		if ( 'refunded' === $new_status ) {
			$refund_amount_cents = (int) $old_transaction->payment_total;
		} elseif ( in_array( $new_status, array( 'partial-refunded', 'partially-refunded' ), true ) ) {
			$refund_amount_cents = (int) round( (float) ( $transaction_data['refund_amount'] ?? 0 ) * 100 );
		}

		if ( $refund_amount_cents <= 0 ) {
			wp_send_json_error(
				array(
					'message' => __( 'Refund amount must be greater than zero.', 'payments-connect-square' ),
				),
				422
			);
		}

		$square_payment_id = $this->resolve_square_payment_id( $old_transaction );
		if ( '' === $square_payment_id ) {
			wp_send_json_error(
				array(
					'message' => __(
						'Square payment ID was not found. Wait for the customer to return from Square, then try again.',
						'payments-connect-square'
					),
				),
				422
			);
		}

		$result = SHC4WC_Refunds::process_refund(
			$square_payment_id,
			$refund_amount_cents / 100,
			$old_transaction->currency,
			'fluentform_refund_' . (int) $old_transaction->id
		);

		if ( is_wp_error( $result ) ) {
			wp_send_json_error(
				array(
					'message' => $result->get_error_message(),
				),
				422
			);
		}

		if ( '' !== $square_payment_id && $square_payment_id !== (string) $old_transaction->charge_id ) {
			\FluentForm\App\Models\Transaction::where( 'id', $transaction_id )->update(
				array(
					'charge_id'  => $square_payment_id,
					'updated_at' => current_time( 'mysql' ),
				)
			);
		}
	}

	/**
	 * @param object $transaction Fluent Forms transaction row.
	 * @return string
	 */
	private function resolve_square_payment_id( $transaction ) {
		$charge_id       = isset( $transaction->charge_id ) ? (string) $transaction->charge_id : '';
		$note            = isset( $transaction->payment_note ) ? (string) $transaction->payment_note : '';
		$square_order_id = SHC4WC_Refunds::parse_square_order_id_from_note( $note );
		$payment_link_id = SHC4WC_Refunds::parse_payment_link_id_from_note( $note );

		if (
			'' !== $charge_id
			&& ! SHC4WC_Refunds::is_internal_checkout_reference( $charge_id )
			&& ( '' === $payment_link_id || $charge_id !== $payment_link_id )
		) {
			return $charge_id;
		}

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

		if ( '' === $payment_link_id && '' !== $charge_id && ! SHC4WC_Refunds::is_internal_checkout_reference( $charge_id ) ) {
			$payment_link_id = $charge_id;
		}

		$settings    = SHC4WC_Plugin::get_settings();
		$location_id = isset( $settings['location_id'] ) ? trim( (string) $settings['location_id'] ) : '';
		$timestamp   = ! empty( $transaction->created_at ) ? strtotime( (string) $transaction->created_at ) : time();

		return SHC4WC_Plugin::instance()->retrieve_square_payment_id_for_hosted_checkout(
			$square_order_id,
			$payment_link_id,
			$location_id,
			$timestamp ? (int) $timestamp : time()
		);
	}
}
