<?php

/**
 * Subscription Checkout Hooks
 *
 * @package ArraySubs\Features\SubscriptionCheckout\Services
 */

namespace ArraySubs\Features\SubscriptionCheckout\Services;

defined('ABSPATH') || exit;

use ArraySubs\Supports\Config;
use ArraySubs\Features\SubscriptionCheckout\Services\Traits\CartValidationTrait;
use ArraySubs\Features\SubscriptionCheckout\Services\Traits\CheckoutDisplayTrait;
use ArraySubs\Features\SubscriptionCheckout\Services\Traits\CheckoutHelpersTrait;
use ArraySubs\Features\SubscriptionCheckout\Services\Traits\CheckoutMigrationTrait;
use ArraySubs\Features\SubscriptionCheckout\Services\Traits\OneClickCheckoutTrait;
use ArraySubs\Features\SubscriptionCheckout\Services\Traits\SubscriptionCreationTrait;
use ArraySubs\Features\SubscriptionCheckout\Services\Traits\TrialCheckoutTrait;

/**
 * Main checkout integration hooks
 */
class Hooks
{
    use CartValidationTrait;
    use CheckoutDisplayTrait;
    use CheckoutHelpersTrait;
    use CheckoutMigrationTrait;
    use OneClickCheckoutTrait;
    use SubscriptionCreationTrait;
    use TrialCheckoutTrait;

    /**
     * Enable auto-loading
     *
     * @var bool
     */
    public static $loadable = true;

    /**
     * Constructor
     */
    public function __construct()
    {
        // Verify helper functions are available
        if (!function_exists('arraysubs_is_subscription_product')) {
            return;
        }
        if (!function_exists('arraysubs_create_subscription')) {
            return;
        }

        // Cart validation - enforce multiple subscription settings
        add_filter('woocommerce_add_to_cart_quantity', [$this, 'limitAddToCartSubscriptionQuantity'], 10, 2);
        add_filter('woocommerce_add_to_cart_validation', [$this, 'validateAddToCart'], 10, 5);
        add_filter('woocommerce_update_cart_validation', [$this, 'validateCartQuantityUpdate'], 10, 4);
        add_action('internal_woocommerce_cart_item_updated_from_user_request', [$this, 'enforceStoreApiSingleProductQuantity'], 10, 4);
        add_action('woocommerce_add_to_cart', [$this, 'enforceSingleProductQuantityOnAdd'], 30, 6);

        // One-click checkout behavior
        add_action('woocommerce_add_to_cart', [$this, 'maybeKeepOnlyOneClickItemInCart'], 20, 6);
        add_filter('woocommerce_add_to_cart_redirect', [$this, 'redirectOneClickPurchasesToCheckout'], 20, 1);
        add_filter('wc_add_to_cart_message_html', [$this, 'maybeSuppressOneClickAddToCartMessage'], 20, 3);
        add_action('template_redirect', [$this, 'maybeRedirectCartPageToCheckout'], 20);
        add_filter('woocommerce_product_supports', [$this, 'disableAjaxAddToCartForOneClick'], 10, 3);
        add_action('template_redirect', [$this, 'sendCheckoutNoCacheHeaders'], 1);
        add_action('wp_enqueue_scripts', [$this, 'enqueueCheckoutSessionGuard'], 20);
        add_action('wp_ajax_arraysubs_checkout_session_state', [$this, 'ajaxCheckoutSessionState']);
        add_action('wp_ajax_nopriv_arraysubs_checkout_session_state', [$this, 'ajaxCheckoutSessionState']);

        // Checkout display - add after order totals (inside order review table, works with AJAX)
        add_action('woocommerce_review_order_after_order_total', [$this, 'displaySubscriptionSummaryInTable']);

        // Checkout migration pricing and metadata.
        add_action('woocommerce_before_calculate_totals', [$this, 'applyCheckoutMigrationPricing'], 30);
        add_filter('arraysubs_subscription_cart_item_data', [$this, 'appendCheckoutMigrationCartItemData'], 10, 4);
        add_action('woocommerce_checkout_create_order_line_item', [$this, 'addCheckoutMigrationOrderItemMeta'], 10, 4);
        add_action('woocommerce_after_checkout_validation', [$this, 'validateCheckoutCustomerRestrictions'], 20, 2);
        add_action('woocommerce_checkout_validate_order_before_payment', [$this, 'validateCheckoutCustomerRestrictionsStoreApi'], 20, 2);
        add_action('arraysubs_order_paid', [$this, 'maybeProcessCheckoutMigrationOrder'], 20, 2);

        // Create subscription on order - Classic Checkout
        add_action('woocommerce_checkout_order_processed', [$this, 'createSubscriptionsFromOrder'], 10, 3);

        // Create subscription on order - Block Checkout (Store API)
        // This hook fires for Block Checkout in WooCommerce 8.0+
        add_action('woocommerce_store_api_checkout_order_processed', [$this, 'createSubscriptionsFromOrderApi'], 10, 1);

        // Also hook into order creation directly as a fallback
        add_action('woocommerce_new_order', [$this, 'maybeCreateSubscriptionsFromNewOrder'], 20, 2);

        // Display subscription info in order details
        add_action('woocommerce_order_details_after_order_table', [$this, 'displayOrderSubscriptions'], 10, 1);

        // Force account creation for subscription purchases (if setting enabled)
        add_filter('woocommerce_checkout_registration_enabled', [$this, 'maybeEnableRegistrationForSubscriptionCheckout'], 10, 1);
        add_filter('woocommerce_checkout_registration_required', [$this, 'maybeRequireRegistration'], 10, 1);
        add_filter('woocommerce_checkout_fields', [$this, 'maybeAddAccountPasswordFieldForSubscriptionCheckout'], 20, 1);

        // Gateway-aware renewal-sync pricing: when Block Checkout persists a
        // payment-method change (Store API checkout PATCH), the cart totals
        // for that request were calculated before the session was updated, so
        // the response would carry the previous gateway's pricing (e.g. a
        // Stripe minimum bump leaking onto Direct bank transfer). Recalculate
        // after the session update so the response reflects the new gateway.
        add_action('woocommerce_store_api_checkout_update_draft', [$this, 'recalculateTotalsForChosenGateway']);

        // Subscription checkout products cannot use cash on delivery.
        add_filter('woocommerce_available_payment_gateways', [$this, 'maybeHideCashOnDeliveryForSubscriptionCheckout'], 20, 1);
        add_filter('woocommerce_available_payment_gateways', [$this, 'maybeHideUnsupportedRenewalSyncGateways'], 21, 1);
        add_action('woocommerce_after_checkout_validation', [$this, 'validateRenewalSyncGatewaySupport'], 30, 2);
        add_action('woocommerce_checkout_validate_order_before_payment', [$this, 'validateRenewalSyncGatewaySupportStoreApi'], 30, 2);

        // Trial checkout: skip payment when trial doesn't require a payment method
        add_filter('woocommerce_cart_needs_payment', [$this, 'maybeSkipPaymentForTrial'], 10, 1);
        add_filter('woocommerce_order_needs_payment', [$this, 'maybeSkipOrderPaymentForTrial'], 10, 2);
        add_filter('woocommerce_payment_complete_order_status', [$this, 'filterSubscriptionPaymentCompleteOrderStatus'], 20, 3);

        // Auto-complete zero-total trial orders when the customer lands on the order-received page.
        // Some gateways (e.g. ones that only capture a card-on-file for trials) do not call
        // payment_complete() themselves when the order total is $0, so the order stays in pending.
        add_action('woocommerce_thankyou', [$this, 'maybeAutoCompleteZeroTrialOrder'], 10, 1);

        // Note: Order status changes and subscription activation is now handled by
        // Subscriptions\Services\OrderIntegration which listens to woocommerce_order_status_changed
    }

    /**
     * Recalculate cart totals after a Store API checkout PATCH persisted a
     * payment-method change, so gateway-aware renewal-sync pricing (raw
     * prorate for manual gateways, minimum-bumped for Stripe) is reflected in
     * the PATCH response instead of lagging one request behind.
     *
     * @return void
     */
    public function recalculateTotalsForChosenGateway(): void
    {
        if (!function_exists('WC') || !WC()->cart || WC()->cart->is_empty()) {
            return;
        }

        foreach (WC()->cart->get_cart() as $cart_item) {
            $check_id = $this->getCartItemProductId($cart_item);

            if ($check_id > 0 && arraysubs_is_subscription_product($check_id)) {
                WC()->cart->calculate_totals();
                return;
            }
        }
    }

    /**
     * Prevent checkout, cart, and order-pay pages from being cached with stale
     * guest/account state. Block checkout depends on per-session Store API data.
     *
     * @return void
     */
    public function sendCheckoutNoCacheHeaders(): void
    {
        if (! $this->isCheckoutSessionSensitivePage()) {
            return;
        }

        if (! defined('DONOTCACHEPAGE')) {
            define('DONOTCACHEPAGE', true);
        }

        if (! defined('DONOTCACHEOBJECT')) {
            define('DONOTCACHEOBJECT', true);
        }

        nocache_headers();
    }

    /**
     * Enqueue the block checkout session guard.
     *
     * @return void
     */
    public function enqueueCheckoutSessionGuard(): void
    {
        if (! $this->isCheckoutSessionSensitivePage() || ! $this->isBlockCheckoutPage()) {
            return;
        }

        $asset_file = Config::get('plugin.public_path') . 'build/checkout-session-guard.asset.php';
        $asset      = file_exists($asset_file)
            ? include $asset_file
            : ['dependencies' => [], 'version' => ARRAYSUBS_VERSION];

        wp_enqueue_script(
            'arraysubs-checkout-session-guard',
            Config::get('plugin.public_url') . 'build/checkout-session-guard.js',
            $asset['dependencies'] ?? [],
            $asset['version'] ?? ARRAYSUBS_VERSION,
            true
        );

        wp_add_inline_script(
            'arraysubs-checkout-session-guard',
            'window.ArraySubsCheckoutSessionGuard = ' . wp_json_encode([
                'ajaxUrl'      => admin_url('admin-ajax.php'),
                'currentUserId' => get_current_user_id(),
                'refreshParam' => 'arraysubs_checkout_session_refresh',
            ]) . ';',
            'before'
        );
    }

    /**
     * Return uncached login state for checkout session reconciliation.
     *
     * @return void
     */
    public function ajaxCheckoutSessionState(): void
    {
        nocache_headers();

        wp_send_json_success([
            'loggedIn' => is_user_logged_in(),
            'userId'   => get_current_user_id(),
        ]);
    }

    /**
     * Check whether the current request is session-sensitive checkout UI.
     *
     * @return bool
     */
    private function isCheckoutSessionSensitivePage(): bool
    {
        if (is_admin() || ! function_exists('is_checkout') || ! function_exists('is_cart')) {
            return false;
        }

        if (is_cart()) {
            return true;
        }

        if (! is_checkout()) {
            return false;
        }

        return ! function_exists('is_wc_endpoint_url') || ! is_wc_endpoint_url('order-received');
    }

    /**
     * Check whether the checkout page uses the WooCommerce Checkout Block.
     *
     * @return bool
     */
    private function isBlockCheckoutPage(): bool
    {
        if (! function_exists('wc_get_page_id') || ! function_exists('has_block')) {
            return false;
        }

        $checkout_page_id = wc_get_page_id('checkout');
        $checkout_page    = $checkout_page_id > 0 ? get_post($checkout_page_id) : null;

        return $checkout_page instanceof \WP_Post && has_block('woocommerce/checkout', $checkout_page);
    }
}
