<?php

if (! defined('ABSPATH')) {
    exit; // Prevent direct access
}

class SibsPaymentCore
{
    protected static $ack_patterns = [
        '/^(000)/',
    ];

    private static function sibs_get_checkout_url($server_mode, $checkout_endpoints)
    {
        return $checkout_endpoints[$server_mode];
    }

    private static function sibs_get_payment_status_url($server_mode, $transaction_id, $checkout_endpoints)
    {
        return $checkout_endpoints[$server_mode] . "/$transaction_id/status";
    }

    private static function sibs_get_back_office_url($server_mode, $reference_id, $back_office_endpoints)
    {
        return $back_office_endpoints[$server_mode] . $reference_id;
    }

    private static function sibs_get_spg_back_office_url($order, $reference_id, $server_mode, $backoffice)
    {
        $end_url = self::get_endpoint($order['payment_type']);

        return $backoffice[$server_mode] . $reference_id . $end_url;
    }

    private static function get_endpoint($payment_type)
    {
        switch($payment_type) {
            case Sibs2\sibsConstants::SPG_PAYMENT_TYPE_CAPT:
                return '/capture';

                break;
            case Sibs2\sibsConstants::SPG_PAYMENT_TYPE_RFND:
                return '/refund';

                break;
            case Sibs2\sibsConstants::SPG_PAYMENT_TYPE_CAUT:
                return '/cancellation';

                break;
            default:
                return '/none';
        }
    }

    private static function sibs_get_ssl_verify($server_mode)
    {
        if (in_array($server_mode, ['DEV', 'TST', 'CER'])) {
            return false;
        }

        return true;
    }

    private static function sibs_get_wp_response($response)
    {
        if (is_wp_error($response)) {
            $result['response'] = 'ERROR_UNKNOWN';
            $result['is_valid'] = false;
            $error_code         = $response->get_error_code();
            $error_message      = $response->get_error_message();
            wc_get_logger()->error('Error Code: ' . wc_print_r($error_code, true), Sibs2\sibsConstants::SIBS_LOG);
            wc_get_logger()->error('Error Message:' . wc_print_r($error_message, true), Sibs2\sibsConstants::SIBS_LOG);

            if (strpos($error_message, 'cURL error 60') !== false) {
                $result['response'] = 'ERROR_MERCHANT_SSL_CERTIFICATE';
            }

            return $result;
        }

        $response      = wp_remote_retrieve_body($response);
        $json_response = json_decode($response, true);

        $result['response'] = isset($json_response) ? $json_response : $response;
        $result['is_valid'] = true;

        return $result;
    }

    private static function sibs_get_headers($token = null, $clientId = null)
    {
        $headers = [
            'content-type' 	=> 'application/json',
            'charset' 			   => 'UTF-8',
        ];

        if (! empty($token)) {
            $headers = array_merge($headers, [
                'Authorization' => "Bearer $token",
            ]);

            if (! empty($clientId)) {
                $headers = array_merge($headers, [
                    'X-IBM-Client-Id' => $clientId,
                ]);
            }
        }

        return $headers;
    }

    private static function sibs_get_response_data($url, $data, $server_mode, $token = null, $clientId = null)
    {
        $data_json = json_encode($data);
        $headers   = self::sibs_get_headers($token, $clientId);

        $args = [
            'headers'   => $headers,
            'body'      => $data_json,
            'sslverify' => self::sibs_get_ssl_verify($server_mode),
            'timeout'   => 100,
        ];

        wc_get_logger()->debug("url: $url", Sibs2\sibsConstants::SIBS_LOG);
        wc_get_logger()->debug('args: ' . print_r($args, true), Sibs2\sibsConstants::SIBS_LOG);

        $response = wp_remote_post($url, $args);

        return self::sibs_get_wp_response($response);
    }

    public static function sibs_get_payment_widget_content($url, $server_mode)
    {
        $args = [
            'sslverify' => self::sibs_get_ssl_verify($server_mode),
        ];

        wc_get_logger()->debug("url: $url", Sibs2\sibsConstants::SIBS_LOG);
        wc_get_logger()->debug('args: ' . print_r($args, true), Sibs2\sibsConstants::SIBS_LOG);

        $response = wp_remote_get($url, $args);

        return self::sibs_get_wp_response($response);
    }

    private static function sibs_get_payment_response($url, $token = null, $clientId = null)
    {
        $headers = self::sibs_get_headers($token, $clientId);

        $args = [
            'headers'   => $headers,
            'sslverify' => false,
        ];

        wc_get_logger()->debug("url: $url", Sibs2\sibsConstants::SIBS_LOG);

        wc_get_logger()->debug('args: ' . print_r($args, true), Sibs2\sibsConstants::SIBS_LOG);

        $response = wp_remote_get($url, $args);

        if (is_wp_error($response)) {
            return false;
        }

        $response = wp_remote_retrieve_body($response);

        return json_decode($response, true);
    }

    /**
     * @return mixed
     */
    public static function getToken()
    {
        $authetication             = [];
        $authetication['token']    = get_option(Sibs2\sibsConstants::SIBS_PLUGIN_PREFIX . '_general_bearer_token');
        $authetication['clientId'] = get_option(Sibs2\sibsConstants::SIBS_PLUGIN_PREFIX . '_general_client_id');

        return $authetication;
    }

    private static function sibs_get_payment_credential($status_parameters)
    {
        $payment_credential             = [];
        $payment_credential['entityId'] = $status_parameters['channel_id'];

        if (! empty($status_parameters['test_mode'])) {
            $payment_credential['testMode'] = $status_parameters['test_mode'];
        }

        return $payment_credential;
    }

    private static function sibs_set_spg_back_office_parameters($order, $reference_id, $order_id)
    {
        wc_get_logger()->debug("order_id: $order_id", Sibs2\sibsConstants::SIBS_LOG);
        wc_get_logger()->debug('BO order: ' . wc_print_r($order, true), Sibs2\sibsConstants::SIBS_LOG);

        $transaction_log = Sibs2\sibsGeneralModels::sibs_get_db_transaction_log($order_id);

        $parameters = [
            'merchant' => [
                'terminalId'            => get_option(Sibs2\sibsConstants::SIBS_PLUGIN_PREFIX . '_general_merchant_no'),
                'channel'               => 'web',
                'merchantTransactionId' => $transaction_log['order_no'],
            ],
            'transaction' => [
                'amount' => [
                    'value'    => floatval(Sibs2\sibsFunctions::sibs_set_number_format($order['amount'])),
                    'currency' => $order['currency'],
                ],
                'description'          => 'woocommerce',
                'transactionTimestamp' => current_time('Y-m-d\TH:i:s.ZP'),
                'originalTransaction'  => [
                    'id'       => $reference_id,
                    'datetime' => $transaction_log['date'],
                ],
            ],
        ];

        return $parameters;
    }

    private static function sibs_is_payment_get_response($payment_status_url, &$payment_response, $token, $clientId)
    {
        for ($i = 0; $i < 3; $i++) {
            $response = true;

            try {
                $payment_response = self::sibs_get_payment_response($payment_status_url, $token, $clientId);
            } catch (Exception $e) {
                $response = false;
            }

            if ($response && $payment_response) {
                return true;
            }
        }

        return false;
    }

    public static function sibs_get_checkout_result($post_data, $server_mode)
    {
        $environment_file   = Sibs2\sibsFunctions::get_environment();
        $checkout_endpoints = $environment_file['checkout_endpoints'];

        $checkout_url  = self::sibs_get_checkout_url($server_mode, $checkout_endpoints);
        $authetication = self::getToken();

        return self::sibs_get_response_data($checkout_url, $post_data, $server_mode, $authetication['token'], $authetication['clientId']);
    }

    public static function sibs_get_payment_widget_url($environment, $checkout_id, $widget_endpoints)
    {
        return $widget_endpoints[$environment] . $checkout_id;
    }

    public static function sibs_get_payment_status($transaction_id, $status_parameters)
    {
        $environment_file   = Sibs2\sibsFunctions::get_environment();
        $checkout_endpoints = $environment_file['checkout_endpoints'];

        $payment_status_url = self::sibs_get_payment_status_url($status_parameters['server_mode'], $transaction_id, $checkout_endpoints);
        $payment_status_url .= '?' . http_build_query(self::sibs_get_payment_credential($status_parameters), '', '&');

        $authetication = self::getToken();

        $response = self::sibs_is_payment_get_response($payment_status_url, $payment_response, $authetication['token'], $authetication['clientId']);

        if ($response) {
            return $payment_response;
        }

        return false;
    }

    public static function sibs_back_office_operation($reference_id, $parameters, $order_id)
    {
        $environment_file = Sibs2\sibsFunctions::get_environment();

        $back_office_url = self::sibs_get_spg_back_office_url($parameters, $reference_id, $parameters['server_mode'], $environment_file['back_office_endpoints']);
        $post_data       = self::sibs_set_spg_back_office_parameters($parameters, $reference_id, $order_id);
        $authetication   = self::getToken();

        $response_data = self::sibs_get_response_data($back_office_url, $post_data, $parameters['server_mode'], $authetication['token'], $authetication['clientId']);

        return $response_data;
    }

    public static function sibs_update_status($reference_id, $status_parameters)
    {
        $environment_file      = Sibs2\sibsFunctions::get_environment();
        $back_office_endpoints = $environment_file['back_office_endpoints'];

        $status_url  = self::sibs_get_back_office_url($status_parameters['server_mode'], $reference_id, $back_office_endpoints);
        $status_url .= '?' . http_build_query(self::sibs_get_payment_credential($status_parameters), '', '&');

        $authetication = self::getToken();

        return self::sibs_get_payment_response($status_url, $authetication['token'], $authetication['clientId']);
    }

    public static function sibs_get_transaction_result($return_code = false)
    {
        wc_get_logger()->debug("return_code: $return_code", Sibs2\sibsConstants::SIBS_LOG);

        if ($return_code === false) {
            wc_get_logger()->debug('transaction_result: ' . Sibs2\sibsConstants::SIBS_NOK, Sibs2\sibsConstants::SIBS_LOG);

            return Sibs2\sibsConstants::SIBS_NOK;
        }

        foreach (self::$ack_patterns as $pattern) {
            if (preg_match($pattern, $return_code)) {
                wc_get_logger()->debug('transaction_result: ' . Sibs2\sibsConstants::SIBS_ACK, Sibs2\sibsConstants::SIBS_LOG);

                return Sibs2\sibsConstants::SIBS_ACK;
            }
        }

        wc_get_logger()->debug('transaction_result: ' . Sibs2\sibsConstants::SIBS_NOK, Sibs2\sibsConstants::SIBS_LOG);

        return Sibs2\sibsConstants::SIBS_NOK;
    }
}
