<?php

defined('ABSPATH') || exit;

require_once plugin_dir_path(__FILE__) . 'includes/class-primer-payments-gateway-functions.php';
require_once plugin_dir_path(__FILE__) . 'includes/class-primer-payments-gateway-helpers.php';
//require_once dirname(__DIR__) . '/admin/includes/primer-admin-options.php';

if (!class_exists('Primer_Options')) {
    require_once PRIMER_PATH . 'admin/includes/primer-admin-options.php';
}

$payment_switch = false;

if ($payment_switch) {

    class WC_Piraeusbank_Gateway extends WC_Payment_Gateway {

        public function __construct() {
            $this->id                 = 'piraeusbank_gateway';
            $this->method_title       = __('Primer Software Payments', 'primer');
            $this->method_description = __('Πληρωμές με Πιστωτικές/Χρεωστικές κάρτες απο Primer Software μέσω Τράπεζας Πειραιώς.', 'primer');
            $this->order_button_text  = __('ΑΓΟΡΑ', 'primer-woocommerce-piraeus-payment-gateway');

            $this->icon = apply_filters('primer-logo', plugins_url('assets/primer_logo_pay.png', __FILE__));

            $this->init_form_fields();
            $this->init_settings();

            $this->title = $this->get_option('title');

            $general_options = get_option('primer_generals');
            $this->enabled   = (!empty($general_options['primer_payments_gateway']) && $general_options['primer_payments_gateway'] === 'on') ? 'yes' : 'no';

            $this->notify_url = WC()->api_request_url('WC_Piraeusbank_Gateway');
            $this->has_fields = ($this->get_option('pb_installments') > 1 ? true : false);

            $this->supports = array(
                'products',
                'refunds',
                'subscriptions',
                'tokenization',
                'subscription_cancellation',
                'add_payment_method',
                'subscription_suspension',
                'subscription_reactivation',
                'subscription_amount_changes',
                'subscription_date_changes',
                'subscription_payment_method_change',
                'subscription_payment_method_change_customer',
                'subscription_payment_method_change_admin',
                'multiple_subscriptions',
            );

            $this->pb_PayMerchantId              = absint($this->get_option('pb_PayMerchantId'));
            $this->pb_AcquirerId                 = absint($this->get_option('pb_AcquirerId'));
            $this->pb_PosId                      = absint($this->get_option('pb_PosId'));
            $this->pb_installments_total_price   = absint($this->get_option('pb_installments_total_price'));
            $this->pb_enable_installments        = sanitize_text_field($this->get_option('pb_enable_installments'));
            $this->description                   = sanitize_text_field($this->get_option('description'));
            $this->instructions                  = sanitize_text_field($this->get_option('instructions'));
            $this->environment                   = sanitize_text_field($this->get_option('environment'));
            $this->pb_Username                   = sanitize_text_field($this->get_option('pb_Username'));
            $this->pb_Password                   = sanitize_text_field($this->get_option('pb_Password'));
            $this->pb_authorize                  = sanitize_text_field($this->get_option('pb_authorize'));
            $this->pb_installments_variation     = sanitize_text_field($this->get_option('pb_installments_variation'));
            $this->pb_enabled_save_payment_token = sanitize_text_field($this->get_option('pb_enabled_save_payment_token'));

            add_action('woocommerce_receipt_' . $this->id, [$this, 'receipt_page']);
            add_action('woocommerce_subscription_failing_payment_method_updated_' . $this->id, [$this, 'update_failing_payment_method'], 10, 2);
            add_action('woocommerce_update_options_payment_gateways_' . $this->id, [$this, 'process_admin_options']);
            add_action('woocommerce_scheduled_subscription_payment_' . $this->id, [$this, 'scheduled_subscription_payment'], 10, 2);
            add_filter('woocommerce_my_subscriptions_payment_method', [$this, 'maybe_render_subscription_payment_method'], 10, 2);
            add_action('wp_enqueue_scripts', [$this, 'enqueue_custom_order_pay_script'], 10);

            add_action('wp', [$this, 'piraeusbank_message']);

            add_action('wp_ajax_primer_validate_bin', array($this, 'ajax_validate_bin'));
            add_action('wp_ajax_nopriv_primer_validate_bin', array($this, 'ajax_validate_bin'));

            $this->PrimerPaymentFunctions = new PrimerPaymentFunctions();
            $this->PrimerPaymentHelpers   = new PrimerPaymentHelpers();
        }

        public function enqueue_custom_order_pay_script() {
            wp_enqueue_script('primer-woocommerce-piraeus-payment-gateway-transactions', plugin_dir_url(__FILE__) . 'includes/js/order_pay.js', array('jquery'), PRIMER_VERSION);
            wp_localize_script('primer-woocommerce-piraeus-payment-gateway-transactions', 'primer_3ds_ajax_obj', array('ajax_url' => admin_url('admin-ajax.php')));
            wp_localize_script('primer-woocommerce-piraeus-payment-gateway-transactions', 'primer_3ds_ajax_obj', array('ajaxurl' => admin_url('admin-ajax.php')));
            wp_register_style('primer-woocommerce-piraeus-payment-gateway-transactions', plugin_dir_url(__FILE__) . 'includes/css/style.css', true, PRIMER_VERSION);
            wp_enqueue_style('primer-woocommerce-piraeus-payment-gateway-transactions');

            wp_localize_script('primer-woocommerce-piraeus-payment-gateway-transactions', 'primer_vars', array(
                'ajax_url' => admin_url('admin-ajax.php'),
                'nonce'    => wp_create_nonce('primer_bin_validation'),
                'i18n'     => array(
                    'invalid_bin'         => __('Please enter a valid 8-digit BIN', 'primer'),
                    'invalid_amount'      => __('Invalid order amount', 'primer'),
                    'validating'          => __('Validating BIN...', 'primer'),
                    'validation_error'    => __('Error validating BIN. Please try again.', 'primer'),
                    'installments'        => __('Select number of installments', 'primer'),
                    'single_payment'      => __('Single Payment', 'primer'),
                    'installments_suffix' => __(' installments', 'primer')
                )
            ));
        }

        public function piraeusbank_message() {
            $order_id = null;

            if (is_cart()) {
                if (isset($_GET['order'])) $order_id = wc_get_order_id_by_order_key($_GET['order']);
            } else {
                $order_id = absint(get_query_var('order-received'));
            }

            $order = wc_get_order($order_id);

            if ($order) {
                if (is_order_received_page() && ('piraeusbank_gateway' == $order->get_payment_method())) {
                    $piraeusbank_message = $order->get_meta('_piraeusbank_message');

                    if (!empty($piraeusbank_message) && is_array($piraeusbank_message)) {
                        $message      = $piraeusbank_message['message'];
                        $message_type = $piraeusbank_message['message_type'];
                        if ($message_type == "success") {
                            add_filter('woocommerce_thankyou_order_received_text', 'piraeusbank_success_message', 10, 2);
                        } else {
                            wc_add_notice($message, $message_type);
                            $order->delete_meta_data('_piraeusbank_message');
                            $order->save();
                        }
                    }

                }
            }
        }

        public function init_form_fields(): void {
            $this->form_fields = array(
                'enabled'                     => array(
                    'title'       => __('Enable', 'primer'),
                    'label'       => __('Enable Primer Payments Gateway', 'primer'),
                    'description' => __('Enable or disable the gateway.', 'primer'),
                    'type'        => 'checkbox',
                    'desc_tip'    => true,
                    'default'     => 'yes'
                ),
                'environment'                 => array(
                    'title'       => __('Test Environment', 'primer'),
                    'description' => __('Enables test environment for Primer Payments Gateway for test cases.', 'primer'),
                    'type'        => 'checkbox',
                    'desc_tip'    => true,
                    'default'     => 'yes'
                ),
                'title'                       => array(
                    'title'       => __('Title', 'primer'),
                    'description' => __('This controls the title which the user sees during checkout.', 'primer'),
                    'default'     => __('Primer Payments Gateway', 'primer'),
                    'type'        => 'text',
                    'desc_tip'    => true
                ),
                'description'                 => array(
                    'title'       => __('Description', 'primer'),
                    'type'        => 'textarea',
                    'description' => __('This controls the description which the user sees during checkout.', 'primer'),
                    'default'     => __('Accepts  Mastercard, Visa cards and etc.', 'primer'),
                ),
                'instructions'                => array(
                    'title'       => __('Instructions', 'primer'),
                    'description' => __('Instructions that will be added to the thank you page and emails.', 'primer'),
                    'type'        => 'textarea',
                    'default'     => '',
                    'desc_tip'    => true,
                ),
                'pb_PayMerchantId'            => array(
                    'title'       => __('Merchant ID', 'primer'),
                    'description' => __('Enter Your Piraeus Bank Merchant ID', 'primer'),
                    'type'        => 'text',
                    'default'     => '',
                    'desc_tip'    => true
                ),
                'pb_AcquirerId'               => array(
                    'title'       => __('Acquirer ID', 'primer'),
                    'description' => __('Enter Your Piraeus Bank Acquirer ID', 'primer'),
                    'type'        => 'text',
                    'default'     => '',
                    'desc_tip'    => true
                ),
                'pb_PosId'                    => array(
                    'title'       => __('POS ID', 'primer'),
                    'description' => __('Enter your Piraeus Bank POS ID', 'primer'),
                    'type'        => 'text',
                    'default'     => '',
                    'desc_tip'    => true
                ),
                'pb_Username'                 => array(
                    'title'       => __('Username', 'primer'),
                    'description' => __('Enter your Piraeus Bank Username', 'primer'),
                    'type'        => 'text',
                    'default'     => '',
                    'desc_tip'    => true
                ),
                'pb_Password'                 => array(
                    'title'       => __('Password', 'primer'),
                    'description' => __('Enter your Piraeus Bank Password', 'primer'),
                    'type'        => 'text',
                    'default'     => '',
                    'desc_tip'    => true
                ),
                'pb_transactions_log'         => array(
                    'title'       => __('Log', 'primer'),
                    'description' => __("Showing 20 latest transactions", 'primer'),
                    'type'        => 'textarea'
                ),
                'pb_enable_installments'      => array(
                    'title'       => __('Enable installments', 'primer'),
                    'description' => __('Check to allow customers to pay in installments', 'primer'),
                    'type'        => 'checkbox',
                    'desc_tip'    => true,
                    'default'     => 'no',
                ),
                'pb_installments_total_price' => array(
                    'title'       => __('Show installments when total price equal or above', 'primer'),
                    'description' => __('Shows installments in checkout page when the price is equal or above the set number', 'primer'),
                    'type'        => 'number',
                    'desc_tip'    => true
                ),
                'pb_enabled_save_payment_token' => array(
                    'title'       => __('Enable/Disable save Payment Methods', 'primer'),
                    'description' => __('Allow customers to save their payment details for future purchases', 'primer'),
                    'type'        => 'checkbox',
                    'desc_tip'    => true,
                    'default'     => 'no',
                )
            );
        }

        public function payment_fields() {
            if ($description = $this->get_description()) {
                echo wpautop(wptexturize($description));
            }
            $this->tokenization_script();
            $this->saved_payment_methods();
        }

        public function tokenization_script(): void {
            wp_enqueue_script('woocommerce-tokenization-form', plugins_url('/assets/js/frontend/tokenization-form' . ('.min') . '.js', WC_PLUGIN_FILE), array('jquery'), WC()->version);
            wp_localize_script('woocommerce-tokenization-form', 'wc_tokenization_form_params', array(
                'is_registration_required' => WC()->checkout()->is_registration_required(),
                'is_logged_in'             => is_user_logged_in()
            ));
        }

        public function maybe_render_subscription_payment_method($payment_method_to_display, $subscription): string {
            $customer_user = $subscription->get_customer_id();

            if ($subscription->get_payment_method() !== $this->id || !$customer_user) {
                return $payment_method_to_display;
            }

            $wc_token = \WC_Payment_Tokens::get(get_post_meta($subscription->get_id(), '_piraeus_source_id', true));

            if ($wc_token != null) {
                $payment_method_to_display = sprintf(__('Via %1$s card ending in %2$s expired in %3$s', 'woocommerce-gateway-stripe'), $wc_token->get_card_type() ?? 'N/A', $wc_token->get_last4() ?? 'Ν/Α', $wc_token->get_expiry_month() . '/' . $wc_token->get_expiry_year());

                return $payment_method_to_display;
            } else {
                return $payment_method_to_display;
            }
        }

        public function saved_payment_methods() {
            $html = '';

            $tokens         = $this->get_tokens();
            $enabled_tokens = $this->pb_enabled_save_payment_token === 'yes' ? true : false;

            $cart           = WC()->cart;
            $order_card     = $cart ? $cart->get_cart() : null;

            foreach ($order_card as $cart_item) {
                $product = $cart_item['data'];
                $product->get_type();
                if ($product->get_type() === 'subscription') {
                    $enabled_tokens = true;
                    break;
                }
            }

            if ($enabled_tokens) {
                $html = '<h5>' . __('For your convenience, your payment information will be securely stored to facilitate faster checkout for future orders or recurring charges. This option ensures a seamless transaction experience while maintaining the highest standards of data protection.', 'primer') . '</h5>';
            }

            $html   .= '<ul class="woocommerce-SavedPaymentMethods wc-saved-payment-methods" data-count="' . esc_attr(count($tokens)). '">';

            foreach ($tokens as $token) {
                $html .= $this->get_saved_payment_method_option_html($token);
            }

            $html .= $this->get_new_payment_method_option_html();
            $html .= $this->add_installments_method_html();
            $html .= '</ul>';

            echo apply_filters('wc_payment_gateway_form_saved_payment_methods_html', $html, $this);
        }

        public function get_saved_payment_method_option_html($token): string {
            $html = sprintf('<li class="woocommerce-SavedPaymentMethods-token">
				<input id="wc-%1$s-payment-token-%2$s" type="radio" name="wc-%1$s-payment-token" value="%2$s" style="width:auto;" class="woocommerce-SavedPaymentMethods-tokenInput" %4$s />
				<label for="wc-%1$s-payment-token-%2$s">%3$s</label>
			     </li>', esc_attr($this->id), esc_attr($token->get_id()), esc_html($token->get_display_name()), checked($token->is_default(), true, false));

            return apply_filters('woocommerce_payment_gateway_get_saved_payment_method_option_html', $html, $token, $this);
        }

        public function is_using_saved_payment_method(): bool {
            $payment_method = isset($_POST['payment_method']) ? wc_clean(wp_unslash($_POST['payment_method'])) : 'piraeusbank_gateway';

            return (isset($_POST['wc-' . $payment_method . '-payment-token']) && 'new' !== $_POST['wc-' . $payment_method . '-payment-token']);
        }

        public function process_payment($order_id) {
            $order = wc_get_order($order_id);

            if ($this->is_using_saved_payment_method()) {
                update_post_meta($order_id, 'is_using_saved_payment', 'true');
                update_post_meta($order_id, 'saved_token_id', $_POST['wc-piraeusbank_gateway-payment-token']);
            } else {
                delete_post_meta($order_id, 'is_using_saved_payment');
                delete_post_meta($order_id, 'saved_token_id');
            }

            if (isset($_POST['wc-piraeusbank_gateway-payment-token']) && $_POST['wc-piraeusbank_gateway-payment-token'] === 'installments') {
                if (!isset($_POST['primer_bin_valid']) || $_POST['primer_bin_valid'] !== '1') {
                    wc_add_notice(__('Please validate your card BIN before proceeding with installments.', 'primer'), 'error');
                    return '';
                }

                $bin         = isset($_POST['primer_bin']) ? sanitize_text_field($_POST['primer_bin']) : '';
                $order_total = $order->get_total();

                if (empty($bin) || strlen($bin) !== 8) {
                    wc_add_notice(__('Invalid card BIN.', 'primer'), 'error');
                    return '';
                }

                $validation = $this->validate_bin($bin, $order_total, $order_id);

                if (!$validation['success']) {
                    wc_add_notice($validation['message'], 'error');
                    return '';
                } else {
                    $installments = isset($_POST['primer_installments']) ? sanitize_text_field($_POST['primer_installments']) : 0;
                    $order->update_meta_data('is_using_installments_payment', true);
                    $order->update_meta_data('installments', $installments);
                    $order->save();
                }
            } else {
                $order->delete_meta_data('is_using_installments_payment');
                $order->delete_meta_data('installments');
                $order->save();
            }

            delete_post_meta($order_id, 'MerchantReference');
            delete_post_meta($order_id, 'threeDSMethodResponseData');
            delete_post_meta($order_id, 'pares');
            delete_post_meta($order_id, 'cres');

            return array(
                'result'   => 'success',
                'redirect' => $order->get_checkout_payment_url(true)
            );
        }

        public function update_failing_payment_method($subscription, $renewal_order): void {
            update_post_meta($subscription->get_id(), '_piraeus_source_id', $renewal_order->get_meta('_piraeus_source_id', true));
            update_post_meta($subscription->get_id(), '_piraeus_card_id', $renewal_order->get_meta('_piraeus_card_id', true));
        }

        public function scheduled_subscription_payment($amount_to_charge, $renewal_order): void {
            $this->PrimerPaymentFunctions->process_payment_with_token($renewal_order, $amount_to_charge);
        }

        public function receipt_page($order): void {
            echo '<p>' . __('Thank you - your order is now pending payment. You should be automatically redirected to Peiraeus Paycenter to make payment.', 'primer-woocommerce-piraeus-payment-gateway') . '</p>';

            echo $this->PrimerPaymentFunctions->generate_piraeusbank_form($order);
        }

        // Installments
        public function add_installments_method_html(): string {
            $order       = null;
            $order_total = 0;
            $order_id    = absint(get_query_var('order-pay'));

            if ($order_id) {
                $order = wc_get_order($order_id);
                if ($order instanceof WC_Order) {
                    $order_total = $order->get_total();
                }
            }

            if (!$order instanceof WC_Order && function_exists('WC') && WC()->cart) {
                $order_total = (float) WC()->cart->get_total('edit');
            }

            $show_installments_field = ($this->pb_enable_installments === 'yes' && $order_total >= $this->pb_installments_total_price);

            if (!$show_installments_field) {
                return '';
            }

            $label           = esc_html__('Pay with installments', 'primer');
            $description     = esc_html__('', 'primer');
            $bin_label       = esc_attr__('Insert the first 8 digits of your card for installments validation', 'primer');
            $bin_placeholder = esc_attr__('8 digits of your card', 'primer');
            $validate_text   = esc_attr__('Validate', 'primer');

            return sprintf('<li class="woocommerce-SavedPaymentMethods-installments">
                            <input id="wc-%1$s-payment-token-installments" type="radio" name="wc-%1$s-payment-token" value="installments" style="width:auto;" class="woocommerce-SavedPaymentMethods-tokenInput" />
                            <label for="wc-%1$s-payment-token-installments">
                                %2$s
                                <span class="woocommerce-SavedPaymentMethods-tokenDescription">%3$s</span>
                            </label>
                            <div class="installments-bin-field" style="display: none;">
                                <p class="form-row form-row-wide" id="primer-bin-field">
                                    <label for="primer-bin">%4$s</label>
                                    <input type="text" id="primer-bin" name="primer_bin" inputmode="numeric" maxlength="8" pattern="\d{8}" autocomplete="cc-number" placeholder="%5$s" />
                                    <button type="button" class="button" id="primer-validate-bin">%6$s</button>
                                    <input type="hidden" id="primer-bin-valid" name="primer_bin_valid" value="0" />
                                    <span class="primer-bin-message" role="status" aria-live="polite" style=""></span>
                                </p>
                            <div>
                        </li>', esc_attr($this->id), $label, $description, $bin_label, $bin_placeholder, $validate_text);
        }

        public function validate_bin($bin, $amount, $order_id = 0) {
            $bin    = trim($bin);
            $amount = (float) $amount;

            if (!preg_match('/^\d{8}$/', $bin)) {
                return [
                    'success' => false,
                    'message' => __('Please enter the first 8 digits of your card.', 'primer')
                ];
            }

            if ($amount <= 0) {
                return [
                    'success' => false,
                    'message' => __('Invalid order amount.', 'primer')
                ];
            }

            $soap_url         = 'https://paycenter.piraeusbank.gr/services/BinServiceClient.asmx';
            $amount_formatted = number_format($amount, 2, '.', '');

            $merchant_id = htmlspecialchars((string) $this->pb_PayMerchantId, ENT_XML1 | ENT_COMPAT, 'UTF-8');
            $acquirer_id = htmlspecialchars((string) $this->pb_AcquirerId, ENT_XML1 | ENT_COMPAT, 'UTF-8');
            $user        = htmlspecialchars((string) $this->pb_Username, ENT_XML1 | ENT_COMPAT, 'UTF-8');
            $password    = htmlspecialchars((string) md5($this->pb_Password), ENT_XML1 | ENT_COMPAT, 'UTF-8');
            $bin_xml     = htmlspecialchars($bin, ENT_XML1 | ENT_COMPAT, 'UTF-8');

            $xml_request = '<?xml version="1.0" encoding="utf-8"?>
                        <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
                          <soap:Body>
                            <GetInstallmentsSupported xmlns="http://piraeusbank.gr/paycenter">
                              <request>
                                <Header>
                                  <Merchant>
                                    <MerchantID>' . $merchant_id . '</MerchantID>
                                    <AcquirerID>' . $acquirer_id . '</AcquirerID>
                                    <User>' . $user . '</User>
                                    <Password>' . $password . '</Password>
                                  </Merchant>
                                </Header>
                                <Body>
                                  <Amount>' . $amount_formatted . '</Amount>
                                  <Bin>' . $bin_xml . '</Bin>
                                </Body>
                              </request>
                            </GetInstallmentsSupported>
                          </soap:Body>
                        </soap:Envelope>';

            $headers = array(
                'Content-Type: text/xml; charset=utf-8',
                'Host: paycenter.piraeusbank.gr',
                'Content-Length: ' . strlen($xml_request)
            );

            $ch = curl_init($soap_url);
            curl_setopt($ch, CURLOPT_POST, true);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $xml_request);
            curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_TIMEOUT, 30);
            curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);

            try {

                $response   = curl_exec($ch);
                $curl_errno = curl_errno($ch);
                $curl_error = curl_error($ch);
                $http_code  = curl_getinfo($ch, CURLINFO_HTTP_CODE);

                curl_close($ch);

                if ($curl_errno !== 0) {
                    throw new Exception('CURL error: ' . $curl_error);
                }

                if ($http_code >= 400) {
                    throw new Exception('HTTP error: ' . $http_code);
                }

                if ($response === false || trim($response) === '') {
                    throw new Exception('Empty response from bank');
                }

                $previous_internal = libxml_use_internal_errors(true);
                $xml               = simplexml_load_string($response);

                if ($xml === false) {
                    $errors = array_map(static function($error) {
                        return trim($error->message ?? '');
                    }, libxml_get_errors());
                    libxml_clear_errors();
                    libxml_use_internal_errors($previous_internal);
                    throw new Exception('Invalid XML response' . (!empty($errors) ? ': ' . implode(' | ', $errors) : ''));
                }

                libxml_clear_errors();
                libxml_use_internal_errors($previous_internal);

                $xml->registerXPathNamespace('soap', 'http://schemas.xmlsoap.org/soap/envelope/');
                $xml->registerXPathNamespace('ns', 'http://piraeusbank.gr/paycenter');

                $body_node = $xml->xpath('//soap:Body/ns:GetInstallmentsSupportedResponse/ns:GetInstallmentsSupportedResult/ns:Body')[0] ?? null;

                if (!$body_node) {
                    throw new Exception('Invalid response format from bank');
                }

                $result_code        = (string) ($body_node->ResultCode ?? '');
                $result_description = (string) ($body_node->ResultDescription ?? '');
                $supports           = (string) ($body_node->SupportsInstallments ?? 'No');
                $max_installments   = (int) ($body_node->Installments ?? 0);

                if ($result_code !== '0' || $supports === 'Error') {
                    $message = !empty($result_description) ? $result_description : __('Card validation failed.', 'primer');

                    return [
                        'success' => false,
                        'message' => __('Card validation failed: ', 'primer') . $message
                    ];
                }
                if ($supports === 'Yes' && $max_installments > 0) {
                    return [
                        'success'              => true,
                        'supportsInstallments' => true,
                        'installments'         => $max_installments,
                        'resultCode'           => $result_code,
                        'resultDescription'    => $result_description,
                        'message'              => sprintf(_n('Your card supports %d installment', 'Your card supports up to %d installments', $max_installments, 'primer'), $max_installments)
                    ];
                }

                return [
                    'success'              => false,
                    'SupportsInstallments' => false,
                    'Installments'         => 1,
                    'message'              => __('Your card does not support installments for this amount.', 'primer')
                ];
            } catch (Exception $e) {
                return [
                    'success' => false,
                    'message' => __('Error processing bank response. Please try again.', 'primer')
                ];
            }
        }

        public function ajax_validate_bin() {
            $order_id    = isset($_POST['order_id']) ? sanitize_text_field($_POST['order_id']) : '';
            $bin         = isset($_POST['bin']) ? sanitize_text_field($_POST['bin']) : '';
            $order_total = isset($_POST['order_total']) ? (float) $_POST['order_total'] : 0;

            $order_total = number_format((float) $order_total, 2, '.', '');

            if (empty($bin) || strlen($bin) !== 8 || !is_numeric($bin)) {
                wp_send_json_error(['message' => __('Please enter a valid 8-digit BIN', 'primer')]);

                return;
            }

            if ($order_total <= 0) {
                wp_send_json_error(['message' => __('Invalid order amount', 'primer')]);

                return;
            }

            $result = $this->validate_bin($bin, $order_total, $order_id);

            $response = [
                'message'              => $result['message'],
                'supportsInstallments' => $result['supportsInstallments'],
                'installments'         => $result['installments'],
                'resultCode'           => $result['resultCode'],
                'resultDescription'    => $result['resultDescription']
            ];

            $result['success'] ? wp_send_json_success($response) : wp_send_json_error($response);

        }

        public function process_refund($order_id, $amount = null, $reason = '') {
            $order = wc_get_order($order_id);

            $amount         = $amount ?? number_format($order->get_remaining_refund_amount(), 2, '.', '');
            $transaction_id = $order->get_transaction_id();

            $mydata_options                 = get_option('primer_mydata');
            $issue_credit_on_refund_enabled = $mydata_options['issue_credit_on_refund'];
            $receipt_status                 = $order->get_meta('receipt_status');

            if (!$order instanceof WC_Order) {
                return new WP_Error('primer_refund_invalid_order', __('Unable to load order for refund.', 'primer'));
            }

            if ($amount <= 0) {
                return new WP_Error('primer_refund_invalid_amount', __('Refund amount must be greater than zero.', 'primer'));
            }

            if (empty($transaction_id)) {
                return new WP_Error('primer_refund_missing_txn', __('No transaction ID is associated with this order.', 'primer'));
            }

            if ($issue_credit_on_refund_enabled === 'on' && $receipt_status === 'issued') {
                if (isset($_POST['line_item_qtys'])) {
                    $qtys       = json_decode(stripslashes($_POST['line_item_qtys']), true) ?: [];
                    $totals     = json_decode(stripslashes($_POST['line_item_totals']), true) ?: [];
                    $tax_totals = json_decode(stripslashes($_POST['line_item_tax_totals']), true) ?: [];
                    $has_qty    = array_sum(array_map('floatval', $qtys)) > 0;

                    $has_manual_total = false;
                    foreach ($totals as $item_id => $total) {
                        if ((float)$total > 0 && (!isset($qtys[$item_id]) || (float)$qtys[$item_id] <= 0)) {
                            $has_manual_total = true;
                            break;
                        }
                    }

                    $has_manual_tax = false;
                    foreach ($tax_totals as $item_id => $taxes) {
                        if (is_array($taxes)) {
                            foreach ($taxes as $tax) {
                                if ((float)$tax > 0 && (!isset($qtys[$item_id]) || (float)$qtys[$item_id] <= 0)) {
                                    $has_manual_tax = true;
                                    break 2;
                                }
                            }
                        }
                    }

                    if ((!$has_qty && ($has_manual_total || $has_manual_tax)) ||
                        ($has_qty && ($has_manual_total || $has_manual_tax))) {
                        return new WP_Error('credit_refund_invalid_method', __('Όταν είναι ενεργή η έκδοση πιστωτικού κατά την επιστροφή χρημάτων μέσω Primer Payments, η επιστροφή πρέπει να πραγματοποιείται αποκλειστικά με ποσότητες ειδών. Μην τροποποιείτε χειροκίνητα ποσά ή φόρους.Εάν επιθυμείτε επιστροφή χρημάτων χρησιμοποιώντας γραμμή επιστροφής ή διαφορετικό ποσό, θα πρέπει πρώτα να απενεργοποιήσετε την επιλογή "Issue credit receipt/invoice if refund" στις ρυθμίσεις MyData Settings.', 'primer'));
                    }
                }
            }

            $result = $this->refund_payment($transaction_id, $amount, $reason, $order);

            if (is_wp_error($result)) {
                return $result;
            }

            $order->add_order_note(sprintf(__('Refunded %1$s via Piraeus Bank. Transaction ID: %3$s, Refund Trace: %2$s. Response: %4$s.', 'primer'), wc_price($amount, ['currency' => $order->get_currency()]), $result['trace_id'], $result['transaction_id'], $result['response_desc']));

            $existing_refunds = $order->get_meta('_piraeus_refunds', true);
            if (empty($existing_refunds) || !is_array($existing_refunds)) {
                $existing_refunds = array();
            }

            $existing_refunds[] = [
                'date'           => current_time('mysql'),
                'amount'         => $amount,
                'trace_id'       => $result['trace_id'],
                'transaction_id' => $result['transaction_id'],
                'response'       => $result['response_desc'],
            ];

            $order->update_meta_data('_piraeus_refunds', $existing_refunds);
            $order->save_meta_data();

            $refunds       = $order->get_refunds();
            $latest_refund = !empty($refunds) ? $refunds[0] : null;
            $refund_id     = $latest_refund ? $latest_refund->get_id() : 0;

            if ($refund_id > 0 && $issue_credit_on_refund_enabled === 'on' && $receipt_status === 'issued') {
                trigger_background_credit($order_id, $refund_id);
            }

            return true;
        }

        public function refund_payment($transaction_id, $amount, $reason, WC_Order $order) {
            $soap_url     = 'https://paycenter.winbank.gr/services/paymentgateway.asmx';
            $request_type = 'REFUND';
            $merchant_ref = uniqid($order->get_id() . '-');

            $currency     = get_woocommerce_currency();
            $amount_value = number_format($amount, 2, '.', '');

            $xml_request = '<?xml version="1.0" encoding="utf-8"?>
                        <soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
                          <soap12:Body>
                            <ProcessTransaction xmlns="http://piraeusbank.gr/paycenter">
                              <TransactionRequest xmlns="http://piraeusbank.gr/paycenter/1.0">
                                <Header>
                                  <RequestType>' . $request_type . '</RequestType>
                                  <MerchantInfo>
                                    <AcquirerID>GR014</AcquirerID>
                                    <MerchantID>' . $this->pb_PayMerchantId . '</MerchantID>
                                    <PosID>' . $this->pb_PosId . '</PosID>
                                    <User>' . $this->pb_Username . '</User>
                                    <Password>' . hash('md5', $this->pb_Password) . '</Password>
                                  </MerchantInfo>
                                </Header>
                                <Body>
                                  <TransactionInfo>
                                    <MerchantReference>' . $merchant_ref . '</MerchantReference>
                                    <TransactionReferenceID>' . esc_html($transaction_id) . '</TransactionReferenceID>
                                    <CurrencyCode>' . $this->PrimerPaymentHelpers->currencyCode[$currency] . '</CurrencyCode>
                                    <Amount>' . $amount_value . '</Amount>
                                    <Description>' . esc_html(wp_trim_words($reason ?: __('WooCommerce refund', 'primer'), 12, '…')) . '</Description>
                                  </TransactionInfo>
                                </Body>
                              </TransactionRequest>
                            </ProcessTransaction>
                          </soap12:Body>
                        </soap12:Envelope>';

            $headers = [
                'Content-Type: application/soap+xml; charset=utf-8',
                'Content-Length: ' . strlen($xml_request),
            ];

            $handle = curl_init($soap_url);
            curl_setopt_array($handle, [
                CURLOPT_POST           => true,
                CURLOPT_POSTFIELDS     => $xml_request,
                CURLOPT_HTTPHEADER     => $headers,
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_TIMEOUT        => 45,
            ]);

            $response = curl_exec($handle);
            $curl_err = curl_error($handle);
            curl_close($handle);

            if ($response === false || !empty($curl_err)) {
                return new WP_Error('primer_refund_transport_error', sprintf(__('Refund request failed: %s', 'primer'), $curl_err ?: __('Empty response from gateway.', 'primer')));
            }

            $xml = simplexml_load_string($response);
            if ($xml === false) {
                return new WP_Error('primer_refund_bad_xml', __('Unable to parse refund response XML.', 'primer'));
            }

            $soapBody = $xml->children('http://www.w3.org/2003/05/soap-envelope')->Body ?? null;
            if (!$soapBody) {
                return new WP_Error('primer_refund_missing_payload', __('Refund response missing SOAP body.', 'primer'));
            }

            $faultNode = $soapBody->children('http://www.w3.org/2003/05/soap-envelope')->Fault ?? null;
            if ($faultNode) {
                $faultCode   = (string) ($faultNode->Code->Value ?? '');
                $faultReason = (string) ($faultNode->Reason->Text ?? __('Unknown SOAP fault', 'primer'));

                return new WP_Error('primer_refund_soap_fault', sprintf(__('SOAP fault %1$s: %2$s', 'primer'), $faultCode, $faultReason));
            }

            $processResponse = $soapBody->children('http://piraeusbank.gr/paycenter')->ProcessTransactionResponse ?? null;
            if (!$processResponse) {
                return new WP_Error('primer_refund_missing_payload', __('Refund response missing ProcessTransactionResponse.', 'primer'));
            }

            $ns = 'http://piraeusbank.gr/paycenter/1.0';
            $transactionResponse = $processResponse->TransactionResponse ?? null;
            if (!$transactionResponse) {
                return new WP_Error('primer_refund_missing_payload', __('Refund response missing TransactionResponse.', 'primer'));
            }

            $children   = $transactionResponse->children($ns);
            $headerNode = $children->Header ?? null;
            $bodyNode   = $children->Body->TransactionInfo ?? null;

            if (!$headerNode || !$bodyNode) {
                return new WP_Error('primer_refund_missing_payload', __('Refund response did not include transaction details.', 'primer'));
            }

            $result_code        = (string) ($headerNode->ResultCode ?? '');
            $result_description = (string) ($headerNode->ResultDescription ?? '');

            if ($result_code !== '0') {
                return new WP_Error('primer_refund_declined', $result_description ?: __('Gateway declined refund.', 'primer'));
            }

            return [
                'transaction_id' => (string) ($bodyNode->TransactionID ?? ''),
                'trace_id'       => (string) ($bodyNode->TraceID ?? $bodyNode->MerchantReference ?? ''),
                'response_code'  => (string) ($bodyNode->ResponseCode ?? ''),
                'response_desc'  => (string) ($bodyNode->ResponseDescription ?? ''),
            ];
        }

    }

    new WC_Piraeusbank_Gateway();
}

function trigger_background_credit($order_id, $refund_id) {
    wp_remote_post(admin_url('admin-ajax.php'), [
        'method'    => 'POST',
        'blocking'  => false,
        'timeout'   => 0.01,
        'sslverify' => false,
        'body'      => [
            'action'    => 'primer_issue_mydata_credit',
            'order_id'  => $order_id,
            'refund_id' => $refund_id
        ],
        'cookies'   => $_COOKIE,
    ]);
}

add_action('wp_ajax_primer_issue_mydata_credit', 'do_credit_with_payment_refund');

function do_credit_with_payment_refund() {
    $order_id  = isset($_POST['order_id']) ? intval($_POST['order_id']) : 0;
    $refund_id = isset($_POST['refund_id']) ? intval($_POST['refund_id']) : 0;

    $order = wc_get_order($order_id);
    if (!$order) wp_die();

    $receipt_id = (int) $order->get_meta('order_id_from_receipt');

    if ($receipt_id > 0) {
        $_POST['receipts']         = [$receipt_id];
        $_POST['primer_refund_id'] = $refund_id;

        if (class_exists('Primer_Options')) {
            (new Primer_Options())->primer_cancel_invoice();
        }
    }

    wp_die();
}
