<?php
/**
 * Authorize.net Echeck Block Integration
 *
 * Integrates the Authorize.net Echeck payment method with WooCommerce Blocks.
 *
 * @package Authorize_Net_Payments_For_Woocommerce
 * @subpackage Authorize_Net_Payments_For_Woocommerce/includes
 */

if (! defined('ABSPATH')) {
    exit;
}

use Automattic\WooCommerce\Blocks\Payments\Integrations\AbstractPaymentMethodType;
use Automattic\WooCommerce\Blocks\Payments\PaymentResult;
use Automattic\WooCommerce\Blocks\Payments\PaymentContext;

/**
 * Class Anet_ECheck_Block
 *
 * Extends WooCommerce Blocks' AbstractPaymentMethodType to support Authorize.net Echeck payments.
 */
class Anet_ECheck_Block extends AbstractPaymentMethodType
{
    /**
     * Payment method name.
     *
     * @var string
     */
    protected $name = ANET_ECHECK_GATEWAY_ID;
    /**
     * Constructor.
     */
    public function __construct()
    {
        /**
         * Hook into WooCommerce Blocks checkout process to inject Authorize.net error handling.
         */
        add_action('woocommerce_rest_checkout_process_payment_with_context', [$this, 'add_authnet_error'], 8, 2);
    }
    /**
     * Initializes the payment method type.
     */
    public function initialize()
    {
        $this->settings = get_option('woocommerce_anet_echeck_settings', []);
    }
    /**
     * Returns if this payment method should be active. If false, the scripts will not be enqueued.
     *
     * @return boolean
     */
    public function is_active()
    {
        $is_active = !empty($this->settings['enabled']) && ANET_YES === $this->settings['enabled'];
        return $is_active;
    }
    /**
     * Returns an array of scripts/handles to be registered for this payment method.
     *
     */
    public function get_payment_method_script_handles()
    {
        $asset_path = plugin_dir_path(__FILE__) . '/../build/index-anet-echeck-block-asset.php';
        $version = ANET_PLUGIN_VERSION;
        $dependencies = [];
        if (file_exists($asset_path)) {
            $asset = require $asset_path;
            $version = is_array($asset) && isset($asset['version']) ? $asset['version'] : $version;
            $dependencies = is_array($asset) && isset($asset['dependencies']) ? $asset['dependencies'] : $dependencies;
        }else{
            Anet_Setting_Helper::log('Asset file not found: ' . $asset_path, ANET_PAYMENT_TYPE_ECHECK, 'warning');
        }
        $js_params = $this->get_gateway_javascript_params();
        if (! empty($js_params['client_key'])) {
            wp_enqueue_script('anet-accept', $js_params['accept_js_url'], $dependencies, null, true); // phpcs:ignore WordPress.WP.EnqueuedResourceParameters.MissingVersion
            $dependencies = array_merge(['anet-accept'], $dependencies);
        }
        // Get WooCommerce version and determine which JS file to load.
        $js_file_path = plugin_dir_path(__FILE__) . '/../build/index-anet-echeck-block.js';
        if (!file_exists($js_file_path)) {
            Anet_Setting_Helper::log('JavaScript file not found: ' . $js_file_path, ANET_PAYMENT_TYPE_ECHECK, 'warning');
            // Return empty array to prevent script registration if JS file is missing.
            return [];
        }
        wp_register_script(
            'anet-echeck-blocks-integration',
            plugins_url('../build/index-anet-echeck-block.js', __FILE__),
            $dependencies,
            $version,
            true
        );
        wp_set_script_translations(
            'anet-echeck-blocks-integration',
            'authorize-net-payments-for-woocommerce'
        );
        return ['anet-echeck-blocks-integration'];
    }
    /**
     * Returns an array of key=>value pairs of data made available to the payment methods script.
     *
     */
    public function get_payment_method_data()
    {
        return array_replace_recursive(
            $this->get_gateway_javascript_params(),
            [
                'title'       => $this->get_title(),
                'description' => $this->get_description(),
                'supports'    => $this->get_supported_features(),
                'tokenization' => $this->get_tokenization() === ANET_YES ? true : false,
                'validate_configuration_key' => $this->get_validate_echeck_configuration_key(),
                'woocommerce_version' => $this->get_woocommerce_version()
            ]
        );
    }
    /**
     * Returns the Authorize Payment Gateway JavaScript configuration object.
     *
     * @return array  the JS configuration from the Authorize Payment Gateway.
     */
    private function get_gateway_javascript_params()
    {
        $js_configuration = [];
        $gateways = WC()->payment_gateways->get_available_payment_gateways();
        if (isset($gateways[ANET_ECHECK_GATEWAY_ID])) {
            $js_configuration = $gateways[ANET_ECHECK_GATEWAY_ID]->javascript_params();
        }
        /**
         * Filter the JavaScript configuration parameters for the Authorize.net eCheck gateway.
         *
         * @since 1.0.0
         * 
         * @param array $js_configuration The configuration array to be passed to the frontend.
         */
        return apply_filters(
            'anet_wc_echeck_params',
            $js_configuration
        );
    }
    /**
     * Returns the title string to use in the UI (customizable via admin settings screen).
     *
     * @return string
     */
    private function get_title()
    {
        $title = isset($this->settings['title']) ? $this->settings['title'] : __('eCheck Block Authorize.net', 'authorize-net-payments-for-woocommerce');
        return $title;
    }
    /**
     * Returns whether tokenization is enabled for the payment method.
     *
     * @return bool
     */
    private function get_tokenization()
    {
        $tokenization = isset($this->settings['tokenization']) ? $this->settings['tokenization'] : false;
        return $tokenization;
    }
    /**
     * Returns the description string to use in the UI.
     *
     * @return string
     */
    private function get_description()
    {
        $description = isset($this->settings['description']) ? $this->settings['description'] : __('Pay securely using your eCheck via Authorize.net.', 'authorize-net-payments-for-woocommerce');
        return $description;
    }
    /**
     * Returns the Key Configuration string to use in the UI.
     *
     * @return string
     */
    private function get_validate_echeck_configuration_key()
    {
        $flag = true;
        $gateways = WC()->payment_gateways->get_available_payment_gateways();
        if (isset($gateways[ANET_ECHECK_GATEWAY_ID])) {
            $gateway = $gateways[ANET_ECHECK_GATEWAY_ID];
            if (empty($gateway->client_key) || empty($gateway->login_id) || empty($gateway->transaction_key)) {
                $flag = false;
            } else {
                $helper = new Anet_Api_Helper(ANET_PAYMENT_TYPE_ECHECK);
                $helper->set_credentials($gateway->login_id, $gateway->transaction_key, $gateway->testmode);
                $flag = $helper->is_authentication_valid();
            }
        } else {
            $flag = false;
        }
        return $flag;
    }
    /**
     * Returns an array of supported features.
     *
     * @return array
     */
    public function get_supported_features()
    {
        $gateways = WC()->payment_gateways->get_available_payment_gateways();
        if (isset($gateways[ANET_ECHECK_GATEWAY_ID])) {
            $gateway = $gateways[ANET_ECHECK_GATEWAY_ID];
            return array_filter($gateway->supports, [$gateway, 'supports']);
        }
        return [];
    }
    /**
     * Get WooCommerce version using multiple fallback methods.
     *
     * @return string WooCommerce version number.
     */
    private function get_woocommerce_version()
    {
        // Method 1: Use WC() function (most reliable).
        if (function_exists('WC') && is_object(WC()) && property_exists(WC(), 'version')) {
            return WC()->version;
        }
        // Method 2: Use WC_VERSION constant.
        if (defined('WC_VERSION')) {
            return WC_VERSION;
        }
        // Method 3: Use WordPress option.
        $version = get_option('woocommerce_version');
        if ($version) {
            return $version;
        }
        // Method 4: Parse plugin data as last resort.
        if (!function_exists('get_plugin_data')) {
            require_once(ABSPATH . 'wp-admin/includes/plugin.php');
        }
        $anet_wc_plugin_file = WP_PLUGIN_DIR . '/woocommerce/woocommerce.php';
        if (file_exists($anet_wc_plugin_file)) {
            $plugin_data = get_plugin_data($anet_wc_plugin_file);
            if (isset($plugin_data['Version'])) {
                return $plugin_data['Version'];
            }
        }
        // Default fallback.
        return '0.0.0';
    }
    /**
     * Add Authorize.net error response to block checkout.
     *
     * @param PaymentContext $context Holds context for the payment.
     * @param PaymentResult  $result  Result object for the payment.
     */
    public function add_authnet_error(PaymentContext $context, PaymentResult &$result)
    {
        if (ANET_ECHECK_GATEWAY_ID === $context->payment_method) {
            add_action(
                'wc_gateway_authorize_net_process_payment_error',
                function ($error) use (&$result) {
                    $payment_details                 = $result->payment_details;
                    $payment_details['errorMessage'] = wp_strip_all_tags($error->getMessage());
                    $result->set_payment_details($payment_details);
                }
            );
        }
    }
}
