<?php

/**
 * Checkout Helpers Trait
 *
 * Shared utility methods used across multiple checkout traits.
 *
 * @package ArraySubs\Features\SubscriptionCheckout\Services\Traits
 */

namespace ArraySubs\Features\SubscriptionCheckout\Services\Traits;

defined('ABSPATH') || exit;

/**
 * Shared checkout helper methods
 */
trait CheckoutHelpersTrait
{
    /**
     * Maybe require registration for subscription purchases
     * If cart contains subscription and auto_create_account is enabled, require registration
     *
     * @param bool $required Current registration requirement
     * @return bool Modified requirement
     */
    public function maybeRequireRegistration(bool $required): bool
    {
        // If already required or user already logged in, don't change
        if ($required || is_user_logged_in()) {
            return $required;
        }

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

        // If cart has subscription and auto_create_account is enabled, require registration
        if (function_exists('arraysubs_is_auto_create_account_enabled') && arraysubs_is_auto_create_account_enabled()) {
            return true;
        }

        return $required;
    }

    /**
     * Remove cash on delivery when the cart contains subscription checkout items.
     *
     * WooCommerce uses the same available-gateways pipeline for classic checkout,
     * checkout blocks, and Store API checkout sessions, so removing COD here keeps
     * the gateway hidden consistently whenever subscription-style checkout behavior
     * is active.
     *
     * @param array<string, \WC_Payment_Gateway> $available_gateways Available payment gateways.
     * @return array<string, \WC_Payment_Gateway>
     */
    public function maybeHideCashOnDeliveryForSubscriptionCheckout(array $available_gateways): array
    {
        if (empty($available_gateways['cod'])) {
            return $available_gateways;
        }

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

        unset($available_gateways['cod']);

        return $available_gateways;
    }

    /**
     * Check whether the current cart contains subscription checkout items.
     *
     * This uses the shared checkout-behavior helper so addon-defined items can
     * opt into the same restrictions without duplicating core gateway logic.
     *
     * @return bool
     */
    private function cartHasSubscriptionCheckoutItems(): bool
    {
        if (!function_exists('WC') || !WC()->cart || !function_exists('arraysubs_is_subscription_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_subscription_checkout_product($product_id)) {
                return true;
            }
        }

        return false;
    }

    /**
     * Get the product ID from the current add-to-cart request.
     *
     * @return int
     */
    private function getRequestedProductId(): int
    {
        $variation_id = filter_input(INPUT_GET, 'variation_id', FILTER_VALIDATE_INT);

        if (!$variation_id) {
            $variation_id = filter_input(INPUT_POST, 'variation_id', FILTER_VALIDATE_INT);
        }

        if ($variation_id && $variation_id > 0) {
            return (int) $variation_id;
        }

        $product_id = filter_input(INPUT_GET, 'add-to-cart', FILTER_VALIDATE_INT);

        if (!$product_id) {
            $product_id = filter_input(INPUT_POST, 'add-to-cart', FILTER_VALIDATE_INT);
        }

        return $product_id && $product_id > 0 ? (int) $product_id : 0;
    }

    /**
     * Get the statuses considered live enough to block or migrate checkout.
     *
     * @return string[]
     */
    private function getRestrictedSubscriptionStatuses(): array
    {
        return ['arraysubs-active', 'arraysubs-on-hold', 'arraysubs-trial', 'arraysubs-pending'];
    }

    /**
     * Resolve the checkout identity used for duplicate checks and migration lookups.
     *
     * @param array $overrides Optional identity overrides.
     * @return array{customer_id:int,email:string}
     */
    private function getCheckoutIdentity(array $overrides = []): array
    {
        $customer_id = absint($overrides['customer_id'] ?? get_current_user_id());
        $email = sanitize_email($overrides['email'] ?? '');

        if (empty($email) && function_exists('WC') && WC()->customer) {
            $email = sanitize_email((string) WC()->customer->get_billing_email());
        }

        if ($customer_id <= 0 && !empty($email)) {
            $matched_user = get_user_by('email', $email);
            if ($matched_user instanceof \WP_User) {
                $customer_id = (int) $matched_user->ID;
            }
        }

        if (empty($email) && $customer_id > 0) {
            $user = get_userdata($customer_id);
            if ($user instanceof \WP_User) {
                $email = sanitize_email($user->user_email);
            }
        }

        return [
            'customer_id' => $customer_id,
            'email'       => $email,
        ];
    }

    /**
     * Build a subscription-only summary of the current cart.
     *
     * @param \WC_Cart|null $cart Cart object.
     * @return array<string,mixed>
     */
    private function getSubscriptionCartSummary($cart = null): array
    {
        $cart = $cart ?: (function_exists('WC') ? WC()->cart : null);

        $summary = [
            'subscription_item_count' => 0,
            'distinct_subscription_count' => 0,
            'first_subscription_product_id' => 0,
            'quantities' => [],
            'trial_item_count' => 0,
            'distinct_trial_count' => 0,
            'trial_quantities' => [],
        ];

        if (!$cart || !method_exists($cart, 'get_cart')) {
            return $summary;
        }

        $distinct_ids = [];
        $trial_distinct_ids = [];

        foreach ($cart->get_cart() as $cart_item) {
            $check_id = $this->getCartItemProductId($cart_item);
            if ($check_id <= 0 || !arraysubs_is_subscription_product($check_id)) {
                continue;
            }

            ++$summary['subscription_item_count'];
            if ($summary['first_subscription_product_id'] <= 0) {
                $summary['first_subscription_product_id'] = $check_id;
            }

            $distinct_ids[$check_id] = true;
            $summary['quantities'][$check_id] = ($summary['quantities'][$check_id] ?? 0) + max(1, absint($cart_item['quantity'] ?? 1));

            if (function_exists('arraysubs_product_has_free_trial') && arraysubs_product_has_free_trial($check_id)) {
                ++$summary['trial_item_count'];
                $trial_distinct_ids[$check_id] = true;
                $summary['trial_quantities'][$check_id] = ($summary['trial_quantities'][$check_id] ?? 0) + max(1, absint($cart_item['quantity'] ?? 1));
            }
        }

        $summary['distinct_subscription_count'] = count($distinct_ids);
        $summary['distinct_trial_count'] = count($trial_distinct_ids);

        return $summary;
    }

    /**
     * Check whether the requested cart state exceeds the single-trial limit.
     *
     * @param int         $check_id                Product or variation ID.
     * @param int         $quantity                Requested quantity.
     * @param string|null $excluded_cart_item_key  Optional cart item key to exclude.
     * @return bool
     */
    private function exceedsAllowedTrialCartQuantity(int $check_id, int $quantity, ?string $excluded_cart_item_key = null): bool
    {
        if (!function_exists('arraysubs_is_one_trial_per_customer') || !arraysubs_is_one_trial_per_customer()) {
            return false;
        }

        if (!function_exists('arraysubs_product_has_free_trial') || !arraysubs_product_has_free_trial($check_id)) {
            return false;
        }

        $total_trial_quantity = max(1, absint($quantity));

        if (!function_exists('WC') || !WC()->cart) {
            return $total_trial_quantity > 1;
        }

        foreach (WC()->cart->get_cart() as $cart_item_key => $cart_item) {
            if ($excluded_cart_item_key !== null && $cart_item_key === $excluded_cart_item_key) {
                continue;
            }

            $item_check_id = $this->getCartItemProductId($cart_item);

            if ($item_check_id <= 0 || !arraysubs_product_has_free_trial($item_check_id)) {
                continue;
            }

            $total_trial_quantity += max(1, absint($cart_item['quantity'] ?? 1));
        }

        return $total_trial_quantity > 1;
    }

    /**
     * Get the cart validation message for single-trial enforcement.
     *
     * @return string
     */
    private function getTrialCartValidationMessage(): string
    {
        return __('Only one free trial can be started per customer. Keep only one trial subscription in the cart and reduce its quantity to 1 before continuing.', 'arraysubs');
    }

    /**
     * Get the effective subscription product or variation ID from a cart item.
     *
     * @param array $cart_item Cart item data.
     * @return int
     */
    private function getCartItemProductId(array $cart_item): int
    {
        $product_id = (int) ($cart_item['product_id'] ?? 0);
        $variation_id = (int) ($cart_item['variation_id'] ?? 0);

        return $variation_id > 0 ? $variation_id : $product_id;
    }
}
