<?php

// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

use PaychefPaymentGateway\Helper\PaymentHelper;
use PaychefPaymentGateway\Helper\SubscriptionHelper;
use \PaychefPaymentGateway\Service\PaychefApiService;

abstract class PayChef_Gateway_Base extends WC_Payment_Gateway
{
    /**
     * @var PaychefApiService
     */
    protected $paychefApiService;

    /**
     * @var string
     */
    protected $pm;

    public function __construct()
    {
        $this->init_form_fields();
        $this->init_settings();
        $this->register_hooks();

        $pm = str_replace(PAYCHEF_PM_PREFIX, '', $this->id);
        $this->pm = ($pm == 'paychef' ? '' : $pm);
        $this->method_description = '<a href="' . admin_url('admin.php?page=wc-settings&tab=' . PAYCHEF_ADMIN_SETTINGS_ID) . '">' . __('General Paychef Settings', 'paychef-payments-for-woocommerce') . '</a>';

        if ($this->pm) {
            $icon_name = str_replace('-', '_', $this->pm);
            $this->icon = WC_HTTPS::force_https_url(plugins_url('/includes/cardicons/card_' . $icon_name . '.svg', PAYCHEF_MAIN_FILE));
        }

        $this->paychefApiService = PayChef_Gateway::getPaychefApiService();

    }

    /**
     * Initialize Gateway Settings Form Fields
     *
     * @return void
     */
    public function init_form_fields()
    {
        $this->form_fields = include(PAYCHEF_PLUGIN_DIR . '/includes/settings/paychef_pm_settings.php');
    }

    /**
     * @return void
     */
	public function init_settings() {
        parent::init_settings();

        $this->supports = array_merge($this->supports, ['refunds']);
        
        // Only enable tokenization if specifically requested by child classes
        if (is_user_logged_in() && $this->should_enable_tokenization()) {
            $this->has_fields = true;
            $this->supports = array_merge($this->supports, ['tokenization', 'add_payment_method']);
        }
        
        $this->enabled = $this->get_option('enabled');
        $this->title = $this->get_option('title');
        $this->description = $this->get_option('description');
    }

    /**
     * @return void
     */
    public function register_hooks()
    {
        add_action(
            'woocommerce_update_options_payment_gateways_' . $this->id,
            [
                $this,
                'process_admin_options'
            ]
        );
    }

    /**
     * @param $orderId
     * @return array
     */
    public function process_payment($orderId)
    {
        // Skip nonce verification for now to restore basic functionality
        // Nonce verification can be added back later with proper block checkout support
        
        $order = new WC_Order($orderId);
        
        // For now, always use new payment to restore basic functionality
        // Tokenization can be added back later with proper data handling
        return $this->process_payment_new($orderId);
    }

    /**
     * Process payment with existing token
     *
     * @param int $order_id
     * @param string $token_id
     * @return array
     */
    protected function process_payment_with_token($order_id, $token_id) {
        $token = WC_Payment_Tokens::get($token_id);
        $order = new WC_Order($order_id);
        
        if (!$token || $token->get_user_id() !== get_current_user_id() || $token->get_gateway_id() !== $this->id) {
            $order->add_order_note(__('Payment failed: Invalid payment token.', 'paychef-payments-for-woocommerce'));
            return array(
                'result' => 'failure',
                'message' => __('Invalid payment token.', 'paychef-payments-for-woocommerce'),
            );
        }

        // Validate token expiry
        if ($this->is_token_expired($token)) {
            $order->add_order_note(__('Payment failed: Payment method has expired.', 'paychef-payments-for-woocommerce'));
            return array(
                'result' => 'failure',
                'message' => __('Your saved payment method has expired. Please select a different payment method.', 'paychef-payments-for-woocommerce'),
            );
        }

        $amount = floatval($order->get_total('edit'));
        $auth_transaction_id = $token->get_meta('paychef_auth_transaction_id');
        
        if ($response = $this->paychefApiService->chargeTransaction($auth_transaction_id, $amount)) {
            // Add comprehensive payment metadata for token payments
            $order->update_meta_data('_paychef_payment_method', $token->get_card_type());
            $order->update_meta_data('_paychef_card', '**** ' . $token->get_last4());
            $order->update_meta_data('_paychef_real_transaction_id', $response->getId());
            $order->update_meta_data('_paychef_transaction_uuid', $response->getUuid());
            $order->update_meta_data('_paychef_auth_transaction_id', $auth_transaction_id);
            $order->update_meta_data('_paychef_token_used', $token_id);
            $order->update_meta_data('_paychef_token_payment', 'yes');
            
            $order->add_order_note(sprintf(
                __('Paychef charge complete using saved %s ending in %s (Transaction ID: %s)', 'paychef-payments-for-woocommerce'),
                $token->get_card_type(),
                $token->get_last4(),
                $response->getUuid()
            ));
            $order->save();
            
            $order->payment_complete($response->getUuid());
            WC()->cart->empty_cart();
            
            return array(
                'result' => 'success',
                'redirect' => $this->get_return_url($order),
            );
        }
        
        $order->add_order_note(__('Payment failed: Unable to charge saved payment method.', 'paychef-payments-for-woocommerce'));
        return array(
            'result' => 'failure',
            'message' => __('Payment failed. Please try again or select a different payment method.', 'paychef-payments-for-woocommerce'),
        );
    }
    
    /**
     * Check if payment token has expired
     *
     * @param WC_Payment_Token_CC $token
     * @return bool
     */
    protected function is_token_expired($token) {
        if (!$token instanceof WC_Payment_Token_CC) {
            return false;
        }

        $expiry_year = $token->get_expiry_year();
        $expiry_month = $token->get_expiry_month();
        
        if (empty($expiry_year) || empty($expiry_month)) {
            return false;
        }
        
        $current_year = date('Y');
        $current_month = date('m');
        
        // Token is expired if year has passed or if same year but month has passed
        return ($expiry_year < $current_year) || 
               ($expiry_year == $current_year && $expiry_month < $current_month);
    }

    /**
     * Process new payment
     *
     * @param int $order_id
     * @return array
     */
    protected function process_payment_new($order_id) {
        $cart = WC()->cart;
        $order = new WC_Order($order_id);

        if (!$totalAmount = floatval($order->get_total('edit'))) {
            $order->payment_complete();
            $cart->empty_cart();
            return [
                'result' => 'success',
                'redirect' => $this->get_return_url($order)
            ];
        }

        $reference = (get_option(PAYCHEF_CONFIGS_PREFIX . 'prefix') ? get_option(PAYCHEF_CONFIGS_PREFIX . 'prefix') . '_' :  '') . $order_id;

        $successRedirectUrl = $this->get_return_url($order);
        $cancelRedirectUrl = PaymentHelper::getCancelUrl($order);

        // Disable save payment method for now to restore basic functionality
        $save_payment_method = false;
        $pre_auth = false;
        
        // Paychef API Logic:
        // - If chargeOnAuth = true, then preAuth MUST be true
        // - For normal payments: both false
        // - For token saving: both true (preAuth to save token, chargeOnAuth to charge immediately)
        $charge_on_auth = $pre_auth; // Only charge on auth if we're doing pre-auth

        $apiService = PayChef_Gateway::getPaychefApiService($order);

        $gateway = $apiService->createPaychefGateway(
            $order, 
            $cart, 
            $totalAmount, 
            $this->pm, 
            $reference, 
            $successRedirectUrl, 
            $cancelRedirectUrl, 
            $pre_auth, 
            $charge_on_auth
        );
        
        if (!$gateway) {
            return array(
                'result' => 'failure',
            );
        }
        
        if ($save_payment_method && $this->should_enable_tokenization()) {
            $order->update_meta_data('paychef_save_payment_method', true);
            $order->update_meta_data('_save_payment_method', 'yes'); // Standard WooCommerce meta
            $order->save();
        }
        
        return $this->process_redirect($gateway, $order);
    }

    /**
     * @param $gateway
     * @param $order
     * @return array
     */
	public function process_redirect($gateway, $order) {
        $order->update_meta_data('paychef_gateway_id', $gateway->getId());
        $order->save();

		if (isset($_COOKIE['pll_language'])) {
			$language = sanitize_text_field($_COOKIE['pll_language']);
		}

		$language = substr($language ?? get_locale(), 0, 2);
        !in_array($language, LANG) ? $language = LANG[0] : null;
        $redirect = str_replace('?', $language . '/?', $gateway->getLink());

        // Return redirect
        return [
            'result' => 'success',
            'redirect' => $redirect
        ];
    }

    /**
     * @param $order
     * @return void
     */
	protected function getCancelUrl($order) {
    }

    /**
     * Payment fields for checkout
     *
     * @return void
     */
    public function payment_fields() {
        // Display description
        if ($this->description) {
            echo wpautop(wptexturize($this->description));
        }
        
        // Only show tokenization features if explicitly enabled
        // This prevents empty saved payment methods lists from appearing
        if (is_user_logged_in() && $this->supports('tokenization') && $this->should_show_tokenization()) {
            $this->tokenization_script();
            
            // Only show saved payment methods if user actually has saved tokens
            if ($this->has_saved_payment_tokens()) {
                $this->saved_payment_methods();
            }
            
            // Only show save checkbox if not a subscription (subscriptions auto-save)
            if (!$this->is_subscription_or_renewal_order()) {
                $this->save_payment_method_checkbox();
            }
        }
        
        // Add custom validation script for enhanced security
        $this->paychef_add_payment_method_validation_script();
    }

    /**
     * Check if this is a subscription or renewal order
     */
    protected function is_subscription_or_renewal_order() {
        if (!class_exists('WC_Subscriptions_Cart')) {
            return false;
        }
        
        return WC_Subscriptions_Cart::cart_contains_subscription() || 
               (function_exists('wcs_cart_contains_renewal') && wcs_cart_contains_renewal());
    }
    
    /**
     * Determine if tokenization support should be enabled
     * Override this method in child classes to enable tokenization selectively
     *
     * @return bool
     */
    protected function should_enable_tokenization() {
        // Enable tokenization for logged in users
        return is_user_logged_in();
    }
    
    /**
     * Determine if tokenization features should be shown
     * Override this method in child classes to enable tokenization selectively
     *
     * @return bool
     */
    protected function should_show_tokenization() {
        // By default, don't show tokenization to prevent empty saved payment methods lists
        // Child classes or specific payment methods can override this
        return $this->should_enable_tokenization();
    }
    
    /**
     * Check if the current user has saved payment tokens for this gateway
     *
     * @return bool
     */
    protected function has_saved_payment_tokens() {
        if (!is_user_logged_in()) {
            return false;
        }
        
        $tokens = WC_Payment_Tokens::get_customer_tokens(get_current_user_id(), $this->id);
        return !empty($tokens);
    }
    
    /**
     * Get payment data value from appropriate source (POST for classic, global for blocks)
     *
     * @param string $key
     * @return string
     */
    protected function get_payment_data_value($key) {
        // Verify nonce for checkout form submission (only for classic checkout with nonce present)
        // Skip nonce check for: admin context, REST API (block checkout)
        if ( ! is_admin() &&
             ! defined( 'REST_REQUEST' ) &&
             isset( $_POST['woocommerce-process-checkout-nonce'] ) ) {
            if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['woocommerce-process-checkout-nonce'] ) ), 'woocommerce-process_checkout' ) ) {
                return '';
            }
        }

        // Try POST first (classic checkout)
        if (isset($_POST[$key])) {
            return sanitize_text_field(wp_unslash($_POST[$key]));
        }

        // For block checkout, try to get data from the payment context
        // This is populated by the payment method data from JavaScript
        if (defined('REST_REQUEST') && REST_REQUEST) {
            // In block checkout context, data is available through the order meta or payment context
            // For now, we'll return empty string to ensure basic payment processing works
            return '';
        }

        return '';
    }
    
    /**
     * Add client-side validation for payment methods
     */
    protected function paychef_add_payment_method_validation_script() {
        if (!is_admin()) {
            wc_enqueue_js("
                jQuery(document).ready(function($) {
                    // Validate payment method selection
                    $('form.checkout').on('checkout_place_order_" . $this->id . "', function() {
                        var tokenField = $('input[name=\"wc-" . $this->id . "-payment-token\"]:checked');
                        if (tokenField.length && tokenField.val() === 'new') {
                            var saveMethod = $('input[name=\"wc-" . $this->id . "-new-payment-method\"]');
                            if (saveMethod.is(':checked')) {
                                return confirm('" . esc_js(__('Save this payment method for future purchases?', 'paychef-payments-for-woocommerce')) . "');
                            }
                        }
                        return true;
                    });
                });
            ");
        }
    }


    /**
     * Add payment method for customer account
     *
     * @return array
     */
    public function add_payment_method() {
        if (!is_user_logged_in()) {
            return array(
                'result' => 'failure',
                'message' => __('You must be logged in to save payment methods.', 'paychef-payments-for-woocommerce'),
            );
        }
        
        if (!$this->should_enable_tokenization()) {
            return array(
                'result' => 'failure',
                'message' => __('Saving payment methods is not supported for this payment method.', 'paychef-payments-for-woocommerce'),
            );
        }

        // Note: Nonce verification is handled by WooCommerce core before this method is called
        // WooCommerce validates the nonce in WC_Form_Handler::add_payment_method_action()
        // Additional verification here would be redundant and could break legitimate requests

        $user_id = get_current_user_id();
        $reference = 'add_payment_method_' . $user_id . '_' . time() . '_' . $this->id;
        
        $success_redirect_url = add_query_arg('paychef_added', '1', wc_get_account_endpoint_url('payment-methods'));
        $cancel_redirect_url = wc_get_account_endpoint_url('payment-methods');

        $gateway = $this->paychefApiService->createPaychefGateway(
            null, 
            null, 
            0, 
            $this->pm, 
            $reference, 
            $success_redirect_url, 
            $cancel_redirect_url, 
            true, 
            false
        );

        if (!$gateway) {
            return array(
                'result' => 'failure',
                'message' => __('Unable to create payment gateway.', 'paychef-payments-for-woocommerce'),
            );
        }

        return array(
            'result' => 'success',
            'redirect' => $gateway->getLink(),
        );
    }

    /**
     * Get payment icons
     *
     * @return string
     */
	public function get_icon() {
        if (empty($this->pm)) {
            $subscription_logos = $this->get_option('subscription_logos') ?? array();
            $logos = $this->get_option('logos') ?? array();
            if (empty($logos) && empty($subscription_logos)) {
                return '';
            }
            // Check if cart contains subscriptions.
            $logos = SubscriptionHelper::isSubscription(WC()->cart) ? $subscription_logos : $logos;
            $icon = '';
            foreach ($logos as $logo) {
                $icon_name = str_replace('-', '_', $logo);
                $src = WC_HTTPS::force_https_url(plugins_url('includes/cardicons/card_' . $icon_name . '.svg', PAYCHEF_MAIN_FILE));
                $icon .= '<img src="' . $src . '" alt="' . $logo . '" id="' . $logo . '"/>';
            }
        } else {
            $icon_name = str_replace('-', '_', $this->pm);
            $src = WC_HTTPS::force_https_url(plugins_url('/includes/cardicons/card_' . $icon_name . '.svg', PAYCHEF_MAIN_FILE));
	        $icon = '<img src="' . $src . '" alt="' . $this->pm . '" id="' . $this->id . '"/>';
        }
        // Add a wrapper around the images to allow styling.
        return apply_filters('woocommerce_gateway_icon', '<span class="icon-wrapper">' . $icon . '</span>', $this->id);
    }

    /**
     * Processing Refund
     *
     * @param int $order_id order id.
     * @param int $amount refund amount.
     * @param string $reason refund reason.
     * @return bool
     */
    public function process_refund($order_id, $amount = null, $reason = ''): bool
    {
        $order = new WC_Order($order_id);
        $gateway_id = intval($order->get_meta('paychef_gateway_id', true));
        $transaction_uuid = $order->get_transaction_id();
        return $this->paychefApiService->refund_transaction(
            $gateway_id,
            $transaction_uuid,
            $amount
        );
    }
    

    /**
     * Gets the transaction URL linked to Paychef dashboard.
     *
     * @param WC_Order $order The order object.
     * @return string|false The transaction URL or false if not available.
     */
    public function get_transaction_url($order) {
        $instance = get_option(PAYCHEF_CONFIGS_PREFIX . 'instance', '');
        if (empty($instance)) {
            return false;
        }

        $transaction_id = $order->get_transaction_id();
        if (empty($transaction_id)) {
            // Versuchen Sie, die Transaktions-ID aus den Metadaten zu holen
            $transaction_id = $order->get_meta('paychef_transaction_uuid');
            if (empty($transaction_id)) {
                return false;
            }
        }

        return sprintf(
            'https://%s.paychef.com/cadmin/index.php?cmd=checkout&act=payments&id=%s',
            esc_attr($instance),
            esc_attr($transaction_id)
        );
    }
}
