<?php

/**
 * Cart Validation Service
 *
 * @package ArraySubs\Features\SubscriptionCheckout\Services
 */

namespace ArraySubs\Features\SubscriptionCheckout\Services;

defined('ABSPATH') || exit;

/**
 * Validate cart items for subscription products
 */
class CartValidation
{
    /**
     * Enable auto-loading
     *
     * @var bool
     */
    public static $loadable = true;

    /**
     * Constructor
     */
    public function __construct()
    {
        add_action('woocommerce_check_cart_items', [$this, 'validateCart']);
        add_action('woocommerce_store_api_cart_errors', [$this, 'validateCartStoreApi'], 10, 2);
    }

    /**
     * Validate cart items (classic cart page)
     */
    public function validateCart(): void
    {
        foreach ($this->getCartValidationErrors() as $error) {
            wc_add_notice($error, 'error');
        }
    }

    /**
     * Validate cart items for Store API (Block Cart / Checkout)
     *
     * @param \WP_Error $errors WP_Error instance to add errors to.
     * @param \WC_Cart  $cart   Cart object.
     */
    public function validateCartStoreApi(\WP_Error $errors, \WC_Cart $cart): void
    {
        foreach ($this->getCartValidationErrors() as $error) {
            $errors->add('arraysubs_cart_error', $error);
        }
    }

    /**
     * Collect cart validation error messages.
     *
     * @return string[]
     */
    private function getCartValidationErrors(): array
    {
        $cart = WC()->cart;

        if (!$cart) {
            return [];
        }

        $errors = [];
        $subscription_count = 0;
        $regular_count = 0;
        $subscription_products = [];
        $subscription_quantities = [];
        $distinct_subscription_products = [];

        // Count subscription vs regular products
        foreach ($cart->get_cart() as $cart_item_key => $cart_item) {
            $product_id = $cart_item['product_id'];
            $variation_id = $cart_item['variation_id'] ?? 0;
            $check_id = $variation_id > 0 ? $variation_id : $product_id;

            if (arraysubs_is_subscription_product($check_id)) {
                ++$subscription_count;
                $subscription_products[] = $cart_item;
                $subscription_quantities[$check_id] = ($subscription_quantities[$check_id] ?? 0) + max(1, absint($cart_item['quantity'] ?? 1));
                $distinct_subscription_products[$check_id] = true;
            } else {
                ++$regular_count;
            }
        }

        // No subscriptions, nothing to validate
        if ($subscription_count === 0) {
            return [];
        }

        // Check if multiple subscriptions are allowed
        $allow_multiple_default = (bool) arraysubs_get_setting('multiple_subscriptions.allow_multiple_in_cart', true);
        $allow_multiple         = apply_filters('arraysubs_allow_multiple_subscriptions', $allow_multiple_default);

        if (!$allow_multiple && count($distinct_subscription_products) > 1) {
            $errors[] = __('Only one subscription plan can be checked out at a time. Remove the extra subscription from your cart before continuing.', 'arraysubs');
        }

        // One subscription per customer: only one distinct subscription allowed in cart
        if (
            function_exists('arraysubs_is_one_subscription_per_customer')
            && arraysubs_is_one_subscription_per_customer()
            && count($distinct_subscription_products) > 1
        ) {
            $errors[] = __('This store allows only one subscription per customer. Keep only one subscription plan in your cart before continuing.', 'arraysubs');
        }

        // Mixed cart check
        $allow_mixed_default = (bool) arraysubs_get_setting('multiple_subscriptions.allow_mixed_cart', true);
        $allow_mixed_cart    = apply_filters('arraysubs_allow_mixed_cart', $allow_mixed_default);

        if (!$allow_mixed_cart && $subscription_count > 0 && $regular_count > 0) {
            $errors[] = __('This order cannot contain subscription and regular products together. Remove the regular product or complete it in a separate checkout.', 'arraysubs');
        }

        if (function_exists('arraysubs_is_one_subscription_per_product') && arraysubs_is_one_subscription_per_product()) {
            foreach ($subscription_quantities as $product_id => $quantity) {
                if ($quantity > 1) {
                    $errors[] = __('Each subscription product can only appear once per order. Reduce the quantity to 1 before continuing.', 'arraysubs');
                    break;
                }
            }
        }

        if (function_exists('arraysubs_is_one_trial_per_customer') && arraysubs_is_one_trial_per_customer()) {
            $trial_quantity = 0;

            foreach ($subscription_quantities as $product_id => $quantity) {
                if (!function_exists('arraysubs_product_has_free_trial') || !arraysubs_product_has_free_trial((int) $product_id)) {
                    continue;
                }

                $trial_quantity += $quantity;

                if ($trial_quantity > 1) {
                    $errors[] = __('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');
                    break;
                }
            }
        }

        // Different billing cycles check
        if ($subscription_count > 1) {
            $allow_different_default = (bool) arraysubs_get_setting('multiple_subscriptions.allow_different_cycles', true);
            $allow_different_cycles  = apply_filters('arraysubs_allow_different_billing_cycles', $allow_different_default);

            if (!$allow_different_cycles) {
                $cycles = [];
                foreach ($subscription_products as $cart_item) {
                    $item_product_id = $cart_item['product_id'];
                    $item_variation  = $cart_item['variation_id'] ?? 0;
                    $item_check_id   = $item_variation > 0 ? $item_variation : $item_product_id;

                    $sub_data = arraysubs_get_product_subscription_data($item_check_id);
                    if ($sub_data) {
                        $cycle_key = $sub_data['period'] . ':' . $sub_data['interval'];
                        $cycles[$cycle_key] = true;
                    }
                }

                if (count($cycles) > 1) {
                    $errors[] = __('These subscription plans use different billing cycles. Keep only plans with the same renewal schedule, or enable different billing cycles in settings.', 'arraysubs');
                }
            }
        }

        // Validate each subscription product
        foreach ($subscription_products as $cart_item) {
            $product_id = $cart_item['product_id'];
            $variation_id = $cart_item['variation_id'] ?? 0;
            $check_id = $variation_id > 0 ? $variation_id : $product_id;

            $subscription_data = arraysubs_get_product_subscription_data($check_id);

            if (!$subscription_data || empty($subscription_data['price'])) {
                $errors[] = __('One or more subscription products have invalid pricing. Please contact support.', 'arraysubs');
            }
        }

        return $errors;
    }
}
