<?php

/**
 * The Card Fields module.
 *
 * @package WooCommerce\PayPalCommerce\CardFields
 */
declare (strict_types=1);
namespace WooCommerce\PayPalCommerce\CardFields;

use DomainException;
use WooCommerce\PayPalCommerce\Vendor\Psr\Log\LoggerInterface;
use WooCommerce\PayPalCommerce\ApiClient\Entity\Order;
use WooCommerce\PayPalCommerce\ApiClient\Factory\ExperienceContextBuilder;
use WooCommerce\PayPalCommerce\CardFields\Service\CardCaptureValidator;
use WooCommerce\PayPalCommerce\Settings\Data\SettingsProvider;
use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExecutableModule;
use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ModuleClassNameIdTrait;
use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ServiceModule;
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway;
use WooCommerce\PayPalCommerce\WcGateway\Helper\CardPaymentsConfiguration;
/**
 * Class CardFieldsModule
 */
class CardFieldsModule implements ServiceModule, ExecutableModule
{
    use ModuleClassNameIdTrait;
    /**
     * {@inheritDoc}
     */
    public function services(): array
    {
        return require __DIR__ . '/../services.php';
    }
    /**
     * {@inheritDoc}
     */
    public function run(ContainerInterface $c): bool
    {
        add_action('init', function () use ($c): void {
            $eligibility_check = $c->get('card-fields.eligibility.check');
            if (!$eligibility_check()) {
                return;
            }
            $this->register_hooks($c);
        });
        return \true;
    }
    /**
     * Registers all hooks that require card-fields eligibility.
     *
     * @param ContainerInterface $c The DI container.
     */
    private function register_hooks(ContainerInterface $c): void
    {
        add_filter('woocommerce_paypal_payments_sdk_components_hook', static function (array $components) use ($c) {
            $dcc_config = $c->get('wcgateway.configuration.card-configuration');
            assert($dcc_config instanceof CardPaymentsConfiguration);
            if (!$dcc_config->is_acdc_enabled()) {
                return $components;
            }
            // Enable the new "card-fields" component.
            $components[] = 'card-fields';
            // Ensure the older "hosted-fields" component is not loaded.
            return array_filter($components, static fn(string $component) => $component !== 'hosted-fields');
        });
        add_filter(
            'woocommerce_credit_card_form_fields',
            /**
             * Return/Param types removed to avoid third-party issues.
             *
             * @psalm-suppress MissingClosureReturnType
             * @psalm-suppress MissingClosureParamType
             */
            function ($default_fields, $id) use ($c) {
                if (!$c->get('wcgateway.configuration.card-configuration')->is_enabled()) {
                    return $default_fields;
                }
                $card_payments_configuration = $c->get('wcgateway.configuration.card-configuration');
                assert($card_payments_configuration instanceof CardPaymentsConfiguration);
                $should_show_card_holder_name = apply_filters('woocommerce_paypal_payments_enable_cardholder_name_field', $card_payments_configuration->show_name_on_card() === 'yes');
                if (CreditCardGateway::ID === $id && $should_show_card_holder_name) {
                    $default_fields['card-name-field'] = '<p class="form-row form-row-wide">
						<label for="ppcp-credit-card-gateway-card-name">' . esc_attr__('Cardholder Name', 'woocommerce-paypal-payments') . '</label>
						<input id="ppcp-credit-card-gateway-card-name" class="input-text wc-credit-card-form-card-expiry" type="text" placeholder="' . esc_attr__('Cardholder Name (optional)', 'woocommerce-paypal-payments') . '" name="ppcp-credit-card-gateway-card-name">
					</p>';
                    // Moves new item to first position.
                    $new_field = $default_fields['card-name-field'];
                    unset($default_fields['card-name-field']);
                    array_unshift($default_fields, $new_field);
                }
                if (apply_filters('woocommerce_paypal_payments_card_fields_translate_card_number', \true)) {
                    if (isset($default_fields['card-number-field'])) {
                        // Replaces the default card number placeholder with a translatable one.
                        $default_fields['card-number-field'] = str_replace('&bull;&bull;&bull;&bull; &bull;&bull;&bull;&bull; &bull;&bull;&bull;&bull; &bull;&bull;&bull;&bull;', esc_attr__('Card number', 'woocommerce-paypal-payments'), $default_fields['card-number-field']);
                    }
                }
                return $default_fields;
            },
            10,
            2
        );
        add_filter('ppcp_create_order_request_body_data', function (array $data, string $payment_method) use ($c): array {
            if (!$c->get('wcgateway.configuration.card-configuration')->is_enabled()) {
                return $data;
            }
            // phpcs:ignore WordPress.Security.NonceVerification.Missing
            if ($payment_method !== CreditCardGateway::ID) {
                return $data;
            }
            $settings = $c->get('settings.settings-provider');
            assert($settings instanceof SettingsProvider);
            $experience_context_builder = $c->get('wcgateway.builder.experience-context');
            assert($experience_context_builder instanceof ExperienceContextBuilder);
            $payment_source_data = array('experience_context' => $experience_context_builder->with_endpoint_return_urls()->build()->to_array());
            $three_d_secure_contingency = $settings->three_d_secure_enum() ? apply_filters('woocommerce_paypal_payments_three_d_secure_contingency', $settings->three_d_secure_enum()) : '';
            if ($three_d_secure_contingency === 'SCA_ALWAYS' || $three_d_secure_contingency === 'SCA_WHEN_REQUIRED') {
                $payment_source_data['attributes'] = array('verification' => array('method' => $three_d_secure_contingency));
            }
            $data['payment_source'] = array('card' => $payment_source_data);
            return $data;
        }, 10, 2);
        // Validates if an order with card payment source can be captured.
        add_action('woocommerce_paypal_payments_before_capture_order', function (Order $order) use ($c) {
            $validator = $c->get('card-fields.service.card-capture-validator');
            assert($validator instanceof CardCaptureValidator);
            if (!$validator->is_valid($order)) {
                $logger = $c->get('woocommerce.logger.woocommerce');
                assert($logger instanceof LoggerInterface);
                $logger->warning("Could not capture order {$order->id()}");
                // Only set session flag if WC session exists (not in API/agentic context).
                /**
                 * Fires to add a delete order flag in WC session.
                 */
                if (apply_filters('woocommerce_paypal_payments_force_delete_wc_order_on_failed_capture', \true) && function_exists('WC') && WC()->session instanceof \WC_Session) {
                    /**
                     * Add delete order flag in WC session to force delete on process payment failure handler.
                     */
                    WC()->session->set('ppcp_delete_wc_order_on_payment_failure', \true);
                }
                throw new DomainException(esc_html__('Could not capture the PayPal order.', 'woocommerce-paypal-payments'));
            }
        });
    }
}
