<?php

/**
 * One-Click Checkout Trait
 *
 * Handles one-click checkout cart behavior, redirects, and AJAX controls.
 *
 * @package ArraySubs\Features\SubscriptionCheckout\Services\Traits
 */

namespace ArraySubs\Features\SubscriptionCheckout\Services\Traits;

defined('ABSPATH') || exit;

/**
 * One-click checkout methods
 */
trait OneClickCheckoutTrait
{
    /**
     * Keep only the current one-click item in cart.
     *
     * @param string $cart_item_key  Cart item key.
     * @param int    $product_id     Product ID.
     * @param int    $quantity       Quantity.
     * @param int    $variation_id   Variation ID.
     * @param array  $variation      Variation data.
     * @param array  $cart_item_data Cart item data.
     * @return void
     */
    public function maybeKeepOnlyOneClickItemInCart(string $cart_item_key, int $product_id, int $quantity, int $variation_id = 0, array $variation = [], array $cart_item_data = []): void
    {
        if (!function_exists('WC') || !WC()->cart || !function_exists('arraysubs_is_one_click_checkout_product')) {
            return;
        }

        $check_id = $variation_id > 0 ? $variation_id : $product_id;

        if (!arraysubs_is_one_click_checkout_product($check_id)) {
            return;
        }

        foreach (WC()->cart->get_cart() as $key => $cart_item) {
            if ($key === $cart_item_key) {
                continue;
            }

            WC()->cart->remove_cart_item($key);
        }

        WC()->cart->set_quantity($cart_item_key, max(1, absint($quantity)), true);
    }

    /**
     * Redirect one-click purchases straight to checkout.
     *
     * @param string $url Redirect URL.
     * @return string
     */
    public function redirectOneClickPurchasesToCheckout(string $url): string
    {
        if (wp_doing_ajax() || !function_exists('arraysubs_is_one_click_checkout_product')) {
            return $url;
        }

        $product_id = $this->getRequestedProductId();

        if ($product_id <= 0 || !arraysubs_is_one_click_checkout_product($product_id)) {
            return $url;
        }

        return wc_get_checkout_url();
    }

    /**
     * Suppress WooCommerce's generic add-to-cart success notice for one-click checkout.
     *
     * When the cart page is disabled, the customer is intentionally sent straight to
     * checkout, so the default "has been added to your cart" message and "View cart"
     * button are misleading noise.
     *
     * @param string $message  Notice HTML.
     * @param array  $products Added product IDs mapped to quantities.
     * @param bool   $show_qty Whether quantities are included in the notice.
     * @return string
     */
    public function maybeSuppressOneClickAddToCartMessage(string $message, array $products, bool $show_qty): string
    {
        if (!$this->shouldSuppressOneClickAddToCartNotice($products)) {
            return $message;
        }

        return '';
    }

    /**
     * Redirect the cart page to checkout when cart page is disabled for one-click flows.
     *
     * @return void
     */
    public function maybeRedirectCartPageToCheckout(): void
    {
        if (
            is_admin()
            || wp_doing_ajax()
            || !function_exists('is_cart')
            || !is_cart()
            || !function_exists('arraysubs_is_cart_page_disabled_for_one_click')
            || !arraysubs_is_cart_page_disabled_for_one_click()
        ) {
            return;
        }

        if (!$this->cartHasOneClickCheckoutItems()) {
            return;
        }

        wp_safe_redirect(wc_get_checkout_url());
        exit;
    }

    /**
     * Disable AJAX add to cart for one-click products so redirects can occur.
     *
     * @param bool         $supports Whether the feature is supported.
     * @param string       $feature  Feature name.
     * @param \\WC_Product $product  Product object.
     * @return bool
     */
    public function disableAjaxAddToCartForOneClick(bool $supports, string $feature, $product): bool
    {
        if (
            $feature !== 'ajax_add_to_cart'
            || !is_object($product)
            || !method_exists($product, 'get_id')
            || !function_exists('arraysubs_is_one_click_checkout_product')
        ) {
            return $supports;
        }

        return arraysubs_is_one_click_checkout_product((int) $product->get_id()) ? false : $supports;
    }

    /**
     * Check whether the current cart contains one-click checkout items.
     *
     * @return bool
     */
    private function cartHasOneClickCheckoutItems(): bool
    {
        if (!function_exists('WC') || !WC()->cart || !function_exists('arraysubs_is_one_click_checkout_product')) {
            return false;
        }

        foreach (WC()->cart->get_cart() as $cart_item) {
            $product_id = !empty($cart_item['variation_id']) && $cart_item['variation_id'] > 0
                ? (int) $cart_item['variation_id']
                : (int) ($cart_item['product_id'] ?? 0);

            if ($product_id > 0 && arraysubs_is_one_click_checkout_product($product_id)) {
                return true;
            }
        }

        return false;
    }

    /**
     * Determine whether the add-to-cart success notice should be hidden.
     *
     * @param array $products Added product IDs mapped to quantities.
     * @return bool
     */
    private function shouldSuppressOneClickAddToCartNotice(array $products): bool
    {
        if (
            !function_exists('arraysubs_is_cart_page_disabled_for_one_click')
            || !arraysubs_is_cart_page_disabled_for_one_click()
            || !function_exists('arraysubs_is_one_click_checkout_product')
        ) {
            return false;
        }

        $product_ids = array_keys($products);
        $requested_product_id = $this->getRequestedProductId();

        if ($requested_product_id > 0) {
            $product_ids[] = $requested_product_id;
        }

        foreach ($product_ids as $product_id) {
            $product_id = absint($product_id);

            if ($product_id > 0 && arraysubs_is_one_click_checkout_product($product_id)) {
                return true;
            }
        }

        return false;
    }
}
