<?php

/**
 * Common operations performed after payment authorization/capture.
 *
 * @package WooCommerce\PayPalCommerce\WcGateway\Processor
 */
declare (strict_types=1);
namespace WooCommerce\PayPalCommerce\WcGateway\Processor;

use WC_Order;
use WooCommerce\PayPalCommerce\ApiClient\Entity\Authorization;
use WooCommerce\PayPalCommerce\ApiClient\Entity\AuthorizationStatus;
use WooCommerce\PayPalCommerce\ApiClient\Entity\Capture;
use WooCommerce\PayPalCommerce\ApiClient\Entity\CaptureStatus;
use WooCommerce\PayPalCommerce\ApiClient\Entity\Order;
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
/**
 * Trait PaymentsStatusHandlingTrait.
 */
trait PaymentsStatusHandlingTrait
{
    /**
     * Changes status of a newly created order, based on the capture/authorization.
     *
     * @param Order    $order The PayPal order.
     * @param WC_Order $wc_order The WC order.
     *
     * @throws RuntimeException If payment denied.
     */
    protected function handle_new_order_status(Order $order, WC_Order $wc_order): void
    {
        if ($order->intent() === 'CAPTURE') {
            $purchase_units = $order->purchase_units();
            if (!empty($purchase_units) && isset($purchase_units[0])) {
                $payments = $purchase_units[0]->payments();
                if ($payments && !empty($payments->captures())) {
                    $this->handle_capture_status($payments->captures()[0], $wc_order);
                }
            }
        } elseif ($order->intent() === 'AUTHORIZE') {
            $purchase_units = $order->purchase_units();
            if (!empty($purchase_units) && isset($purchase_units[0])) {
                $payments = $purchase_units[0]->payments();
                if ($payments && !empty($payments->authorizations())) {
                    $this->handle_authorization_status($payments->authorizations()[0], $wc_order);
                }
            }
        }
    }
    /**
     * Changes the order status, based on the capture.
     *
     * @param Capture  $capture The capture.
     * @param WC_Order $wc_order The WC order.
     *
     * @throws RuntimeException If payment denied.
     */
    protected function handle_capture_status(Capture $capture, WC_Order $wc_order): void
    {
        $status = $capture->status();
        $details = $status->details();
        if ($details) {
            $this->add_status_details_note($wc_order, $status->name(), $details->text());
        }
        switch ($status->name()) {
            case CaptureStatus::COMPLETED:
                $wc_order->payment_complete();
                /**
                 * Fired when PayPal order is captured.
                 */
                do_action('woocommerce_paypal_payments_order_captured', $wc_order, $capture);
                break;
            // It is checked in the capture endpoint already, but there are other ways to capture,
            // such as when paid via saved card.
            case CaptureStatus::DECLINED:
                $fraud = $capture->fraud_processor_response();
                $status_note = $fraud && $fraud->response_code() ? sprintf(
                    /* translators: %s - processor response code and description */
                    __('Could not capture the payment. Processor response: %s', 'woocommerce-paypal-payments'),
                    $fraud->get_response_code_message()
                ) : __('Could not capture the payment.', 'woocommerce-paypal-payments');
                $wc_order->update_status('failed', $status_note);
                $decline_message = $fraud ? $fraud->get_customer_decline_message() : __('Payment provider declined the payment, please use a different payment method.', 'woocommerce-paypal-payments');
                throw new RuntimeException($decline_message);
            case CaptureStatus::PENDING:
            case CaptureStatus::FAILED:
                $wc_order->update_status('on-hold', __('Awaiting payment.', 'woocommerce-paypal-payments'));
                break;
        }
    }
    /**
     * Changes the order status, based on the authorization.
     *
     * @param Authorization $authorization The authorization.
     * @param WC_Order      $wc_order The WC order.
     *
     * @throws RuntimeException If payment denied.
     */
    protected function handle_authorization_status(Authorization $authorization, WC_Order $wc_order): void
    {
        $status = $authorization->status();
        $details = $status->details();
        if ($details) {
            $this->add_status_details_note($wc_order, $status->name(), $details->text());
        }
        switch ($status->name()) {
            case AuthorizationStatus::CREATED:
            case AuthorizationStatus::PENDING:
                $wc_order->update_status('on-hold', __('Awaiting payment.', 'woocommerce-paypal-payments'));
                /**
                 * Fired when PayPal order is authorized.
                 */
                do_action('woocommerce_paypal_payments_order_authorized', $wc_order, $authorization);
                break;
            case AuthorizationStatus::DENIED:
                $wc_order->update_status('failed', __('Could not get the payment authorization.', 'woocommerce-paypal-payments'));
                throw new RuntimeException(__('Payment provider declined the payment, please use a different payment method.', 'woocommerce-paypal-payments'));
        }
    }
    /**
     * Adds the order note with status details.
     *
     * @param WC_Order $wc_order The WC order to which the note will be added.
     * @param string   $status The status name.
     * @param string   $reason The status reason.
     */
    protected function add_status_details_note(WC_Order $wc_order, string $status, string $reason): void
    {
        $wc_order->add_order_note(sprintf(
            /* translators: %1$s - PENDING, DENIED, ... %2$s - text explaining the reason, ... */
            __('PayPal order payment is set to %1$s status, details: %2$s', 'woocommerce-paypal-payments'),
            $status,
            $reason
        ));
        $wc_order->save();
    }
}
