<?php
/**
 * Cart price calculation for tier and package pricing
 */

if (!defined('ABSPATH')) {
    exit;
}

if (!class_exists('WC_TPP_Cart')) {
    class WC_TPP_Cart {

    public function __construct() {
        add_action('woocommerce_before_calculate_totals', array($this, 'apply_tier_package_pricing'), 10, 1);
        add_filter('woocommerce_cart_item_price', array($this, 'display_cart_item_price'), 10, 3);
        add_filter('woocommerce_cart_item_subtotal', array($this, 'display_cart_item_subtotal'), 10, 3);
        add_filter('woocommerce_add_to_cart_validation', array($this, 'validate_package_quantity'), 10, 3);
        add_filter('woocommerce_cart_item_quantity', array($this, 'maybe_hide_cart_quantity_input'), 999, 3);
        add_filter('woocommerce_widget_cart_item_quantity', array($this, 'maybe_hide_mini_cart_quantity_input'), 999, 3);
        add_action('wp_head', array($this, 'add_cart_quantity_css'));

        // WooCommerce Blocks support
        add_filter('woocommerce_store_api_product_quantity_editable', array($this, 'block_quantity_editable'), 10, 2);
    }

    public function apply_tier_package_pricing($cart) {
        if (is_admin() && !defined('DOING_AJAX')) {
            return;
        }

        // Prevent infinite loops
        if (did_action('woocommerce_before_calculate_totals') >= 2) {
            return;
        }

        // Check if cart object is valid
        if (!$cart || !is_a($cart, 'WC_Cart')) {
            return;
        }

        foreach ($cart->get_cart() as $cart_item_key => $cart_item) {
            $product_id = $cart_item['product_id'];
            $variation_id = isset($cart_item['variation_id']) ? absint($cart_item['variation_id']) : 0;
            $effective_id = $variation_id > 0 ? $variation_id : $product_id;
            $quantity = $cart_item['quantity'];
            $product = $cart_item['data'];

            // Validate product object
            if (!$product || !is_a($product, 'WC_Product')) {
                continue;
            }

            // Check for exact package match first (pass product_id for parent fallback support)
            $package_price = null;
            if (get_option('wc_tpp_enable_package_pricing') === 'yes') {
                $package_price = WC_TPP_Frontend::get_package_price($product_id, $quantity, $variation_id);
            }

            if ($package_price !== null) {
                // Apply package pricing (total price divided by quantity)
                $unit_price = $package_price / $quantity;
                $product->set_price($unit_price);
                // Store pricing information in cart item for display
                WC()->cart->cart_contents[$cart_item_key]['wc_tpp_pricing_type'] = 'package';
                WC()->cart->cart_contents[$cart_item_key]['wc_tpp_total_price'] = $package_price;
            } else {
                // Apply tier pricing if no package match (pass product_id for parent fallback support)
                if (get_option('wc_tpp_enable_tier_pricing') === 'yes') {
                    $tier_price = WC_TPP_Frontend::get_tier_price($product_id, $quantity, $variation_id);
                    if ($tier_price !== null) {
                        $product->set_price($tier_price);
                        // Store pricing information in cart item for display
                        WC()->cart->cart_contents[$cart_item_key]['wc_tpp_pricing_type'] = 'tier';
                        WC()->cart->cart_contents[$cart_item_key]['wc_tpp_unit_price'] = $tier_price;
                    }
                }
            }
        }
    }

    public function display_cart_item_price($price, $cart_item, $cart_item_key) {
        if (isset($cart_item['wc_tpp_pricing_type'])) {
            if ($cart_item['wc_tpp_pricing_type'] === 'package') {
                $total_price = isset($cart_item['wc_tpp_total_price']) ? $cart_item['wc_tpp_total_price'] : $cart_item['line_total'];
                $unit_price = $total_price / $cart_item['quantity'];
                return wc_price($unit_price) . ' <small class="wc-tpp-notice">(' . __('Package price', 'wc-tier-package-prices') . ')</small>';
            } elseif ($cart_item['wc_tpp_pricing_type'] === 'tier') {
                $unit_price = isset($cart_item['wc_tpp_unit_price']) ? $cart_item['wc_tpp_unit_price'] : $cart_item['data']->get_price();
                return wc_price($unit_price) . ' <small class="wc-tpp-notice">(' . __('Volume discount', 'wc-tier-package-prices') . ')</small>';
            }
        }
        return $price;
    }

    public function display_cart_item_subtotal($subtotal, $cart_item, $cart_item_key) {
        if (isset($cart_item['wc_tpp_pricing_type']) && $cart_item['wc_tpp_pricing_type'] === 'package') {
            $total_price = isset($cart_item['wc_tpp_total_price']) ? $cart_item['wc_tpp_total_price'] : $cart_item['line_total'];
            return wc_price($total_price);
        }
        return $subtotal;
    }

    public function validate_package_quantity($passed, $product_id, $quantity) {
        // Check for variation ID in request (for variable products)
        $variation_id = isset($_REQUEST['variation_id']) ? absint($_REQUEST['variation_id']) : 0;

        // Check if restriction is enabled (with parent fallback for variations)
        if (!$this->is_restriction_enabled($product_id, $variation_id)) {
            return $passed;
        }

        // Get packages for this product/variation (with parent fallback)
        $packages = $this->get_packages_with_fallback($product_id, $variation_id);

        if (!$packages) {
            return $passed;
        }

        // Check if the quantity matches any package
        $valid_quantity = false;
        $available_quantities = array();

        foreach ($packages as $package) {
            $available_quantities[] = $package['qty'];
            if ($quantity == $package['qty']) {
                $valid_quantity = true;
                break;
            }
        }

        if (!$valid_quantity) {
            $product = wc_get_product($product_id);
            $product_name = $product ? $product->get_name() : __('this product', 'wc-tier-package-prices');

            wc_add_notice(
                sprintf(
                    __('The quantity %1$d is not available for %2$s. Please choose from the available package sizes: %3$s', 'wc-tier-package-prices'),
                    $quantity,
                    $product_name,
                    implode(', ', $available_quantities)
                ),
                'error'
            );
            return false;
        }

        return $passed;
    }

    public function maybe_hide_cart_quantity_input($product_quantity, $cart_item_key, $cart_item) {
        $product_id = $cart_item['product_id'];
        $variation_id = isset($cart_item['variation_id']) ? absint($cart_item['variation_id']) : 0;
        $effective_id = $variation_id > 0 ? $variation_id : $product_id;

        // Check if restriction is enabled (with parent fallback) and packages exist
        if ($this->is_restriction_enabled($product_id, $variation_id) && $this->get_packages_with_fallback($product_id, $variation_id)) {
            return sprintf('<span class="wc-tpp-cart-quantity wc-tpp-restricted-qty" data-product-id="%d">%s</span>',
                $effective_id,
                $cart_item['quantity']
            );
        }

        return $product_quantity;
    }

    public function maybe_hide_mini_cart_quantity_input($product_quantity, $cart_item, $cart_item_key) {
        $product_id = $cart_item['product_id'];
        $variation_id = isset($cart_item['variation_id']) ? absint($cart_item['variation_id']) : 0;
        $effective_id = $variation_id > 0 ? $variation_id : $product_id;

        // Check if restriction is enabled (with parent fallback) and packages exist
        if ($this->is_restriction_enabled($product_id, $variation_id) && $this->get_packages_with_fallback($product_id, $variation_id)) {
            return sprintf('<span class="wc-tpp-cart-quantity wc-tpp-restricted-qty" data-product-id="%d">%s &times;</span>',
                $effective_id,
                $cart_item['quantity']
            );
        }

        return $product_quantity;
    }

    public function add_cart_quantity_css() {
        // Get all cart items and check which products have restrictions
        if (!function_exists('WC') || !WC()->cart || is_admin()) {
            return;
        }

        $restricted_products = array();
        foreach (WC()->cart->get_cart() as $cart_item) {
            $product_id = $cart_item['product_id'];
            $variation_id = isset($cart_item['variation_id']) ? absint($cart_item['variation_id']) : 0;
            $effective_id = $variation_id > 0 ? $variation_id : $product_id;

            // Check if restriction is enabled (with parent fallback) and packages exist
            if ($this->is_restriction_enabled($product_id, $variation_id) && $this->get_packages_with_fallback($product_id, $variation_id)) {
                $restricted_products[] = $effective_id;
            }
        }

        if (!empty($restricted_products)) {
            echo '<style type="text/css">';
            foreach ($restricted_products as $product_id) {
                // Hide quantity inputs for restricted products in cart (classic cart)
                echo '.cart_item .wc-tpp-restricted-qty[data-product-id="' . esc_attr($product_id) . '"] + .quantity,';
                echo '.cart_item .wc-tpp-restricted-qty[data-product-id="' . esc_attr($product_id) . '"] ~ .quantity,';
                echo '.woocommerce-mini-cart-item .wc-tpp-restricted-qty[data-product-id="' . esc_attr($product_id) . '"] + .quantity,';
                echo '.woocommerce-mini-cart-item .wc-tpp-restricted-qty[data-product-id="' . esc_attr($product_id) . '"] ~ .quantity { display: none !important; }';

                // Hide WooCommerce blocks quantity selector for restricted products
                echo '.wc-block-cart-item[data-product-id="' . esc_attr($product_id) . '"] .wc-block-components-quantity-selector,';
                echo '.wc-block-mini-cart__items .wc-block-cart-item[data-product-id="' . esc_attr($product_id) . '"] .wc-block-components-quantity-selector { display: none !important; }';
            }
            echo '</style>';
        }
    }

    /**
     * Make quantity non-editable for restricted products in WooCommerce blocks
     *
     * @param bool $editable Whether the quantity is editable
     * @param WC_Product $product Product object (can be variation)
     * @return bool
     */
    public function block_quantity_editable($editable, $product) {
        // Validate product object
        if (!$product || !is_a($product, 'WC_Product')) {
            return $editable;
        }

        $product_id = $product->get_id();

        if (!$product_id) {
            return $editable;
        }

        // For variations, get parent product ID and variation ID
        $variation_id = 0;
        $parent_id = $product_id;

        if ($product->is_type('variation')) {
            $variation_id = $product_id;
            $parent_id = $product->get_parent_id();
        }

        // Check if restriction is enabled (with parent fallback) and packages exist
        if ($this->is_restriction_enabled($parent_id, $variation_id) && $this->get_packages_with_fallback($parent_id, $variation_id)) {
            return false;
        }

        return $editable;
    }

    /**
     * Get packages with parent fallback for variations
     *
     * @param int $product_id Parent product ID
     * @param int $variation_id Variation ID (0 for simple products)
     * @return array|false Packages array or false if none found
     */
    private function get_packages_with_fallback($product_id, $variation_id = 0) {
        $effective_id = $variation_id > 0 ? $variation_id : $product_id;
        $packages = get_post_meta($effective_id, '_wc_tpp_packages', true);

        // Fall back to parent pricing if variation doesn't have its own pricing
        if ((empty($packages) || !is_array($packages)) && $variation_id > 0) {
            $packages = get_post_meta($product_id, '_wc_tpp_packages', true);
        }

        return (!empty($packages) && is_array($packages)) ? $packages : false;
    }

    /**
     * Check if restriction is enabled for a product/variation with parent fallback
     *
     * @param int $product_id Parent product ID
     * @param int $variation_id Variation ID (0 for simple products)
     * @return bool Whether restriction is enabled
     */
    private function is_restriction_enabled($product_id, $variation_id = 0) {
        $effective_id = $variation_id > 0 ? $variation_id : $product_id;
        $global_restrict = get_option('wc_tpp_restrict_package_quantities', 'no') === 'yes';
        $product_restrict = get_post_meta($effective_id, '_wc_tpp_restrict_to_packages', true) === 'yes';

        // Fall back to parent restriction setting if variation doesn't have its own
        if (!$product_restrict && $variation_id > 0) {
            $product_restrict = get_post_meta($product_id, '_wc_tpp_restrict_to_packages', true) === 'yes';
        }

        return $global_restrict || $product_restrict;
    }
}

new WC_TPP_Cart();
}
