<?php

namespace Sibs\Stargate\Api;

use Sibs\Stargate\Constants\OrderStatus;
use Sibs\Stargate\Constants\PaymentStatus;
use Sibs\Stargate\Constants\PaymentTypes;
use Sibs\Stargate\Constants\WoocommerceOrderStatus;
use Sibs\Stargate\Exceptions\SibsException;
use Sibs\Stargate\Loggers\SibsLogger;
use Sibs\Stargate\Models\SibsGeneralModels;
use Sibs\Stargate\Utils\SibsVersion;

defined('ABSPATH') || exit;

class Refund extends ApiAbstract
{
    /**
     * SIBS: Process.
     *
     * @param null|float $amount
     * @param string     $reason
     *
     * @return bool|\WP_Error
     */
    public static function process(\WC_Order $wc_order, $amount, $reason = '')
    {
        try {
            SibsLogger::debug("[process_refund] order_id: {$wc_order->get_id()}");
            SibsLogger::debug("Refund Reason: {$reason}");

            $is_sibs_payment = SibsVersion::sibs_is_order_from_sibs($wc_order);

            if (!$is_sibs_payment) {
                throw new SibsException(
                    __('Order is not a SIBS payment', 'sibs-woo-stg')
                );
            }

            $payment_status = $wc_order->get_status();
            $status_to_refund = [
                OrderStatus::PROCESSING,
                OrderStatus::COMPLETED,
                OrderStatus::PARTIALLY_CAPTURED,
                OrderStatus::PARTIALLY_REFUNDED,
            ];

            if (!in_array($payment_status, $status_to_refund)) {
                throw new SibsException(
                    sprintf(
                        __('Order is cannot be refunded in status %s', 'sibs-woo-stg'),
                        esc_attr($payment_status)
                    )
                );
            }

            $sibs_payment = SibsGeneralModels::get_transaction($wc_order);
            $payment_type = PaymentTypes::RFND;
            $error_message = __('Refund request has an ERROR', 'sibs-woo-stg');

            $log_sibs_payment = $sibs_payment;
            $log_sibs_payment['formConfig']
            = $log_sibs_payment['formConfig'] = json_decode($log_sibs_payment['formConfig'], true);
            $log_sibs_payment['spg_style'] = json_decode($log_sibs_payment['spg_style'], true);

            SibsLogger::debug('[process_refund] sibs_payment', [
                'data' => $log_sibs_payment,
            ]);

            $backoffice_config = self::get_backoffice_config(
                $sibs_payment,
                $payment_type,
                $amount,
                $error_message
            );

            $backoffice_result = self::sibs_do_back_office_payment($wc_order, $backoffice_config);
            SibsGeneralModels::update_transaction($wc_order, [
                'refunded_id' => $backoffice_result['response']['transactionID'],
                'refund_status' => $backoffice_result['response']['paymentStatus'],
            ]);

            if (!$backoffice_result['is_valid']) {
                throw new SibsException($error_message);
            }

            switch ($backoffice_result['response']['paymentStatus']) {
                case PaymentStatus::SUCCESS:
                    $refund_status = $backoffice_config['order_status'];
                    SibsLogger::debug('[process_refund] SUCCESS');

                    break;

                case PaymentStatus::PENDING:
                    $refund_status = WoocommerceOrderStatus::PENDING_REFUND;
                    SibsLogger::debug('[process_refund] PENDING');

                    break;

                default:
                    throw new SibsException(
                        __('Refund request denied by SIBS', 'sibs-woo-stg')
                    );
            }

            $amountMSG = "{$amount} {$wc_order->get_currency()}";

            $note_message = sprintf(
                // translators: Amount Message
                __('Order was Refunded for %s', 'sibs-woo-stg'),
                $amountMSG
            );

            try {
                $wc_order->update_status($refund_status);
            } catch (\Throwable $t) {
                SibsLogger::error($t->getMessage());
            }

            SibsGeneralModels::update_transaction($wc_order, [
                'payment_status' => $refund_status,
                'refunded_amount' => $backoffice_result['response']['amount']['value'] + $sibs_payment['refunded_amount'],
                'refund_information' => $note_message.(!empty($sibs_payment['refund_information']) ? ', '.$sibs_payment['refund_information'] : ''),
            ]);

            if (PaymentStatus::PENDING === $backoffice_result['response']['paymentStatus']) {
                return new \WP_Error(
                    'refund_pending',
                    __('BLIK Refund is asyncronous, you have to make a refund inquiry to get the real refund status', 'sibs-woo-stg'),
                    ['status' => 200]
                );
            }

            return true;
        } catch (SibsException $e) {
            return new \WP_Error(
                'not_refunded_error',
                $e->getErrorMessage(),
                ['status' => 400]
            );
        } catch (\Exception $e) {
            return new \WP_Error(
                'not_refunded_error',
                $e->getMessage(),
                ['status' => 500]
            );
        }
    }

    /**
     * SIBS Refund Async Order Add Button.
     *
     * @param mixed $order
     */
    public static function add_button($order)
    {
        $order_id = esc_attr($order->get_id());
        self::print_button($order_id, '6', esc_attr(__('SIBS Refund', 'sibs-woo-stg')));
    }
}
