<?php

namespace Sibs\Stargate\Core;

use Sibs\Stargate\Config\SibsConfig;
use Sibs\Stargate\Constants\Environments;
use Sibs\Stargate\Constants\PaymentTypes;
use Sibs\Stargate\Constants\Plugin;
use Sibs\Stargate\Exceptions\StgException;
use Sibs\Stargate\Loggers\SibsLogger;
use Sibs\Stargate\Models\SibsGeneralModels;
use Sibs\Stargate\Utils\SibsEnvironment;

defined('ABSPATH') || exit;

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

    /**
     * SIBS Get Base URL.
     */
    public static function sibs_get_base_url(): string
    {
        SibsLogger::debug('Entrou em sibs_get_base_url');
        $environment_file = new SibsEnvironment();
        $base_urls = $environment_file->get_base_urls();
        $default_environment = $environment_file->get_default_environment();
        $environment = SibsConfig::getEnvironment();

        return $base_urls[$environment] ?? $base_urls[$default_environment] ?? '';
    }

    /**
     * SIBS Get Payment Widget URL.
     */
    public static function sibs_get_payment_widget_url(string $transaction_id): string
    {
        SibsLogger::debug('Entrou em sibs_get_payment_widget_url');
        $environment_file = new SibsEnvironment();
        $widget_base_urls = $environment_file->get_widget_base_urls();
        $default_environment = $environment_file->get_default_environment();
        $environment = SibsConfig::getEnvironment();

        $widget_base_url = $widget_base_urls[$environment] ?? $widget_base_urls[$default_environment] ?? '';

        return "https://{$widget_base_url}/assets/js/widget.js?id={$transaction_id}";
    }

    /**
     * SIBS Get Checkout Result.
     *
     * @return array
     */
    public static function sibs_get_checkout_result(array $post_data)
    {
        SibsLogger::debug('Entrou em sibs_get_checkout_result');
        $checkout_url = self::sibs_get_checkout_url();

        return self::sibs_get_response_data($checkout_url, $post_data);
    }

    /**
     * SIBS Get Payment Status.
     *
     * @return array|\WP_Error
     */
    public static function sibs_get_payment_status(string $transaction_id)
    {
        SibsLogger::debug('Entrou em sibs_get_payment_status');

        $payment_status_url = self::sibs_get_back_office_url($transaction_id);

        return self::sibs_get_payment_response($payment_status_url);
    }

    /**
     * SIBS Back Office Operation.
     *
     * @return array
     */
    public static function sibs_back_office_operation(\WC_Order $wc_order, string $transaction_id, array $parameters)
    {
        SibsLogger::debug('Entrou em sibs_back_office_operation');

        $back_office_url = self::sibs_get_back_office_url($transaction_id, $parameters['payment_type']);
        $post_data = self::sibs_set_back_office_parameters($wc_order, $transaction_id, $parameters);

        return self::sibs_get_response_data($back_office_url, $post_data);
    }

    /**
     * SIBS Update Status.
     *
     * @return array|\WP_Error
     */
    public static function sibs_update_status(string $transaction_id)
    {
        SibsLogger::debug('Entrou em sibs_update_status');

        $back_office_url = self::sibs_get_back_office_url($transaction_id);

        return self::sibs_get_payment_response($back_office_url);
    }

    /**
     * SIBS Get Transaction Result.
     *
     * @param bool|string $return_code
     */
    public static function sibs_get_transaction_result($return_code = false): string
    {
        SibsLogger::debug('Entrou em sibs_get_transaction_result');
        SibsLogger::debug("return_code: {$return_code}");

        if (false === $return_code) {
            SibsLogger::debug('transaction_result: '.Plugin::NOK);

            return Plugin::NOK;
        }

        foreach (self::$ack_patterns as $pattern) {
            if (preg_match($pattern, $return_code)) {
                SibsLogger::debug('transaction_result: '.Plugin::ACK);

                return Plugin::ACK;
            }
        }

        SibsLogger::debug('transaction_result: '.Plugin::NOK);

        return Plugin::NOK;
    }

    /**
     * SIBS Get Return Code.
     */
    public static function sibs_get_return_code(array $payment_result): string
    {
        $payment_result = $payment_result['response'] ?? $payment_result;
        $payment_result = $payment_result['returnStatus'] ?? $payment_result;
        $payment_result = $payment_result['respObject'] ?? $payment_result;

        return $payment_result['statusCode']
            ?? $payment_result['code']
            ?? StgException::ERROR_CODE;
    }

    /**
     * SIBS Get Return Message.
     */
    public static function sibs_get_return_msg(array $payment_result): string
    {
        $payment_result = $payment_result['response'] ?? $payment_result;
        $payment_result = $payment_result['returnStatus'] ?? $payment_result;
        $payment_result = $payment_result['respObject'] ?? $payment_result;

        return $payment_result['statusMsg']
            ?? StgException::ERROR_UNKNOWN;
    }

    /**
     * SIBS Get Checkout URL.
     */
    private static function sibs_get_checkout_url(): string
    {
        SibsLogger::debug('Entrou em sibs_get_checkout_url');
        $base_url = self::sibs_get_base_url();
        $environment_file = new SibsEnvironment();
        $api_version = $environment_file->get_api_version();

        return "https://{$base_url}/api/{$api_version}/payments";
    }

    /**
     * SIBS Get SPG BackOffice URL.
     */
    private static function sibs_get_back_office_url(string $transaction_id, string $payment_type = 'INQUIRY'): string
    {
        SibsLogger::debug('Entrou em sibs_get_back_office_url');
        $checkout_url = self::sibs_get_checkout_url();
        $endpoint = self::get_endpoint($payment_type);

        return "{$checkout_url}/{$transaction_id}/{$endpoint}";
    }

    /**
     * Get Endpoint.
     */
    private static function get_endpoint(string $payment_type): string
    {
        SibsLogger::debug('Entrou em get_endpoint');

        switch ($payment_type) {
            case PaymentTypes::CAPT:
                return 'capture';

            case PaymentTypes::RFND:
                return 'refund';

            case PaymentTypes::CAUT:
                return 'cancellation';

            case 'INQUIRY':
            default:
                return 'status';
        }
    }

    /**
     * SIBS Get SSL Verify.
     */
    private static function sibs_get_ssl_verify(): bool
    {
        SibsLogger::debug('Entrou em sibs_get_ssl_verify');
        $environment = SibsConfig::getEnvironment();

        if (
            in_array($environment, [
                Environments::DEV,
                Environments::TST,
                Environments::QLY,
                Environments::CER,
            ])
        ) {
            return false;
        }

        return false; // Always false due to cURL issues in some environments
    }

    /**
     * SIBS Get WP Response.
     *
     * @param mixed $response
     */
    private static function sibs_get_wp_response($response): array
    {
        SibsLogger::debug('Entrou em sibs_get_wp_response');
        if (is_wp_error($response)) {
            $result['response'] = __('Unfortunately, your transaction has failed. Please try again', 'sibs-woo-stg');
            $result['is_valid'] = false;
            $error_code = $response->get_error_code();
            $error_message = $response->get_error_message();
            SibsLogger::error('Error Code: '.$error_code);
            SibsLogger::error('Error Message: '.$error_message);

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

            return $result;
        }

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

        $result['response'] = $json_response ?? $response;
        $result['is_valid'] = true;

        SibsLogger::debug('result', [
            'data' => $result,
        ]);

        return $result;
    }

    /**
     * SIBS Get Headers.
     */
    private static function sibs_get_headers(): array
    {
        SibsLogger::debug('Entrou em sibs_get_headers');

        $token = SibsConfig::getToken();
        $clientId = SibsConfig::getClientId();

        $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;
    }

    /**
     * SIBS Get Response Data.
     *
     * @return array
     */
    private static function sibs_get_response_data(string $url, array $data)
    {
        SibsLogger::debug('Entrou em sibs_get_response_data');
        $data_json = json_encode($data);
        $headers = self::sibs_get_headers();

        $args = [
            'headers' => $headers,
            'body' => $data_json,
            'sslverify' => self::sibs_get_ssl_verify(),
            'conn_timeout' => 90,
            'timeout' => 90,
            'sibs_request' => true,
        ];

        $logArgs = $args;
        $logArgs['body'] = json_decode($logArgs['body'], true);

        SibsLogger::debug("[sibs_get_response_data] url: {$url}");
        SibsLogger::debug('[sibs_get_response_data] args', [
            'args' => $logArgs,
        ]);

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

        return self::sibs_get_wp_response($response);
    }

    /**
     * SIBS Get Payment Response.
     *
     * @param string $url
     *
     * @return array|\WP_Error
     */
    private static function sibs_get_payment_response($url)
    {
        SibsLogger::debug('Entrou em sibs_get_payment_response');
        $headers = self::sibs_get_headers();

        $args = [
            'headers' => $headers,
            'sslverify' => self::sibs_get_ssl_verify(),
            'timeout' => 30,
        ];

        SibsLogger::debug("url: {$url}");
        SibsLogger::debug('args', [
            'data' => $args,
        ]);

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

        if (is_wp_error($response)) {
            SibsLogger::debug('wp_remote_get: failed', [
                'url' => $url,
                'error_code' => $response->get_error_code(),
                'error_message' => $response->get_error_message(),
                'error_data' => $response->get_error_data(),
            ]);

            return false;
        }

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

        SibsLogger::debug('response', [
            'data' => $response,
        ]);

        return $response;
    }

    /**
     * SIBS Set Back Office Parameters.
     */
    private static function sibs_set_back_office_parameters(
        \WC_Order $wc_order,
        string $transaction_id,
        array $parameters
    ): array {
        SibsLogger::debug('Entrou em sibs_set_back_office_parameters');
        SibsLogger::debug("order_id: {$wc_order->get_id()}");
        SibsLogger::debug('BO order', [
            'parameters' => $parameters,
        ]);

        $transaction = SibsGeneralModels::get_transaction($wc_order);

        return [
            'merchant' => [
                'terminalId' => SibsConfig::getTerminalId(),
                'channel' => SibsConfig::getChannel(),
                'merchantTransactionId' => $transaction['order_no'],
            ],
            'transaction' => [
                'amount' => [
                    'value' => floatval(SibsFunctions::sibs_set_number_format($parameters['amount'])),
                    'currency' => $parameters['currency'],
                ],
                'description' => SibsConfig::getEcommerceName(),
                'transactionTimestamp' => wp_date('Y-m-d\TH:i:s.vP'),
                'originalTransaction' => [
                    'id' => $transaction_id,
                    'datetime' => $transaction['date'],
                ],
            ],
        ];
    }
}