<?php

/**
 * The PayPal API Exception.
 *
 * @package WooCommerce\PayPalCommerce\ApiClient\Exception
 */
declare (strict_types=1);
namespace WooCommerce\PayPalCommerce\ApiClient\Exception;

use stdClass;
/**
 * Class PayPalApiException
 */
class PayPalApiException extends \WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException
{
    /**
     * The JSON response object of PayPal.
     *
     * @var stdClass
     */
    private $response;
    /**
     * The HTTP status code of the PayPal response.
     *
     * @var int
     */
    private $status_code;
    /**
     * PayPalApiException constructor.
     *
     * @param stdClass|null $response The JSON object.
     * @param int           $status_code The HTTP status code.
     */
    public function __construct(?stdClass $response = null, int $status_code = 0)
    {
        if (is_null($response)) {
            $response = new stdClass();
        }
        if (!isset($response->message)) {
            $response->message = sprintf(
                /* translators: %1$d - HTTP status code number (404, 500, ...) */
                __('Unknown error while connecting to PayPal. Status code: %1$d.', 'woocommerce-paypal-payments'),
                $this->status_code
            );
        }
        if (!isset($response->name)) {
            $response->name = __('Error', 'woocommerce-paypal-payments');
        }
        if (!isset($response->details)) {
            $response->details = array();
        }
        if (!isset($response->links) || !is_array($response->links)) {
            $response->links = array();
        }
        /**
         * The JSON response object.
         *
         * @var stdClass $response
         */
        $this->response = $response;
        $this->status_code = $status_code;
        $message = $this->get_customer_friendly_message($response);
        if ($response->name) {
            $message = '[' . $response->name . '] ' . $message;
        }
        foreach ($response->links as $link) {
            if (isset($link->rel) && 'information_link' === $link->rel) {
                $message .= ' ' . $link->href;
            }
        }
        parent::__construct($message, $status_code);
    }
    /**
     * The name of the exception.
     *
     * @return string
     */
    public function name(): string
    {
        return $this->response->name;
    }
    /**
     * The details of the Exception.
     *
     * @return array
     */
    public function details(): array
    {
        return $this->response->details;
    }
    /**
     * Whether a certain detail is part of the exception reason.
     *
     * @param string $issue The issue.
     *
     * @return bool
     */
    public function has_detail(string $issue): bool
    {
        foreach ($this->details() as $detail) {
            if (isset($detail->issue) && $detail->issue === $issue) {
                return \true;
            }
        }
        return \false;
    }
    /**
     * The HTTP status code.
     *
     * @return int
     */
    public function status_code(): int
    {
        return $this->status_code;
    }
    /**
     * Return exception details if exists.
     *
     * @param string $error The error to return in case no details found.
     * @return string
     */
    public function get_details(string $error): string
    {
        if (empty($this->details())) {
            return $error;
        }
        $details = '';
        foreach ($this->details() as $detail) {
            $issue = $detail->issue ?? '';
            $field = $detail->field ?? '';
            $description = $detail->description ?? '';
            $details .= $issue . ' ' . $field . ' ' . $description . '<br>';
        }
        return $details;
    }
    /**
     * Returns a friendly message if the error detail is known.
     *
     * @param stdClass $json The response.
     * @return string
     */
    public function get_customer_friendly_message(stdClass $json): string
    {
        if (empty($json->details)) {
            return $json->message;
        }
        $improved_keys_messages = array('PAYMENT_DENIED' => __('PayPal rejected the payment. Please reach out to the PayPal support for more information.', 'woocommerce-paypal-payments'), 'TRANSACTION_REFUSED' => __('The transaction has been refused by the payment processor. Please reach out to the PayPal support for more information.', 'woocommerce-paypal-payments'), 'DUPLICATE_INVOICE_ID' => __('The transaction has been refused because the Invoice ID already exists. Please create a new order or reach out to the store owner.', 'woocommerce-paypal-payments'), 'PAYER_CANNOT_PAY' => __('There was a problem processing this transaction. Please reach out to the store owner.', 'woocommerce-paypal-payments'), 'PAYEE_ACCOUNT_RESTRICTED' => __('There was a problem processing this transaction. Please reach out to the store owner.', 'woocommerce-paypal-payments'), 'AGREEMENT_ALREADY_CANCELLED' => __('The requested agreement is already canceled. Please reach out to the PayPal support for more information.', 'woocommerce-paypal-payments'));
        $improved_errors = array_filter(array_keys($improved_keys_messages), function ($key) use ($json): bool {
            foreach ($json->details as $detail) {
                if (isset($detail->issue) && $detail->issue === $key) {
                    return \true;
                }
            }
            return \false;
        });
        if ($improved_errors) {
            $improved_errors = array_values($improved_errors);
            return $improved_keys_messages[$improved_errors[0]];
        }
        return $json->message;
    }
}