<?php
/**
 * Cart Handler
 *
 * @package WC_Composable_Product
 */

namespace WC_Composable_Product;

defined('ABSPATH') || exit;

/**
 * Cart Handler Class
 *
 * Handles adding composable products to cart and calculating prices
 */
class Cart_Handler {
    /**
     * Stock manager instance
     *
     * @var Stock_Manager
     */
    private $stock_manager;

    /**
     * Constructor
     */
    public function __construct() {
        $this->stock_manager = new Stock_Manager();

        add_filter('woocommerce_add_to_cart_validation', [$this, 'validate_add_to_cart'], 10, 3);
        add_filter('woocommerce_add_cart_item_data', [$this, 'add_cart_item_data'], 10, 2);
        add_filter('woocommerce_get_cart_item_from_session', [$this, 'get_cart_item_from_session'], 10, 2);
        add_filter('woocommerce_get_item_data', [$this, 'display_cart_item_data'], 10, 2);
        add_action('woocommerce_before_calculate_totals', [$this, 'calculate_cart_item_price']);
        add_action('woocommerce_single_product_summary', [$this, 'render_product_selector'], 25);
        add_action('woocommerce_checkout_create_order_line_item', [$this->stock_manager, 'store_selected_products_in_order'], 10, 3);
    }

    /**
     * Render product selector on product page
     */
    public function render_product_selector() {
        global $product;

        if ($product && $product->get_type() === 'composable') {
            Product_Selector::render($product);
        }
    }

    /**
     * Validate add to cart
     *
     * @param bool $passed Validation status
     * @param int $product_id Product ID
     * @param int $quantity Quantity
     * @return bool
     */
    public function validate_add_to_cart($passed, $product_id, $quantity) {
        $product = wc_get_product($product_id);

        if (!$product || $product->get_type() !== 'composable') {
            return $passed;
        }

        // Check if selected products are provided
        if (!isset($_POST['composable_products']) || empty($_POST['composable_products'])) {
            wc_add_notice(__('Please select at least one product.', 'wc-composable-product'), 'error');
            return false;
        }

        $selected_products = array_map('absint', $_POST['composable_products']);
        $selection_limit = $product->get_selection_limit();

        // Validate selection limit
        if (count($selected_products) > $selection_limit) {
            /* translators: %d: selection limit */
            wc_add_notice(sprintf(__('You can select a maximum of %d products.', 'wc-composable-product'), $selection_limit), 'error');
            return false;
        }

        if (count($selected_products) === 0) {
            wc_add_notice(__('Please select at least one product.', 'wc-composable-product'), 'error');
            return false;
        }

        // Validate that selected products are valid
        $available_products = $product->get_available_products();
        $available_ids = array_map(function($p) {
            return $p->get_id();
        }, $available_products);

        foreach ($selected_products as $selected_id) {
            if (!in_array($selected_id, $available_ids)) {
                wc_add_notice(__('One or more selected products are not available.', 'wc-composable-product'), 'error');
                return false;
            }
        }

        // Validate stock availability
        $stock_validation = $this->stock_manager->validate_stock_availability($selected_products, $quantity);
        if ($stock_validation !== true) {
            wc_add_notice($stock_validation, 'error');
            return false;
        }

        return $passed;
    }

    /**
     * Add cart item data
     *
     * @param array $cart_item_data Cart item data
     * @param int $product_id Product ID
     * @return array
     */
    public function add_cart_item_data($cart_item_data, $product_id) {
        $product = wc_get_product($product_id);

        if (!$product || $product->get_type() !== 'composable') {
            return $cart_item_data;
        }

        if (isset($_POST['composable_products']) && !empty($_POST['composable_products'])) {
            $selected_products = array_map('absint', $_POST['composable_products']);
            $cart_item_data['composable_products'] = $selected_products;

            // Make cart item unique
            $cart_item_data['unique_key'] = md5(json_encode($selected_products) . time());
        }

        return $cart_item_data;
    }

    /**
     * Get cart item from session
     *
     * @param array $cart_item Cart item
     * @param array $values Values from session
     * @return array
     */
    public function get_cart_item_from_session($cart_item, $values) {
        if (isset($values['composable_products'])) {
            $cart_item['composable_products'] = $values['composable_products'];
        }

        return $cart_item;
    }

    /**
     * Display cart item data
     *
     * @param array $item_data Item data
     * @param array $cart_item Cart item
     * @return array
     */
    public function display_cart_item_data($item_data, $cart_item) {
        if (isset($cart_item['composable_products']) && !empty($cart_item['composable_products'])) {
            $product_names = [];
            foreach ($cart_item['composable_products'] as $product_id) {
                $product = wc_get_product($product_id);
                if ($product) {
                    $product_names[] = $product->get_name();
                }
            }

            if (!empty($product_names)) {
                $item_data[] = [
                    'key' => __('Selected Products', 'wc-composable-product'),
                    'value' => implode(', ', $product_names),
                ];
            }
        }

        return $item_data;
    }

    /**
     * Calculate cart item price
     *
     * @param \WC_Cart $cart Cart object
     */
    public function calculate_cart_item_price($cart) {
        if (is_admin() && !defined('DOING_AJAX')) {
            return;
        }

        // Use static flag to prevent multiple executions
        static $already_calculated = false;
        if ($already_calculated) {
            return;
        }

        foreach ($cart->get_cart() as $cart_item_key => $cart_item) {
            if (isset($cart_item['data']) && $cart_item['data']->get_type() === 'composable') {
                if (isset($cart_item['composable_products']) && !isset($cart_item['composable_price_calculated'])) {
                    $product = $cart_item['data'];
                    $price = $product->calculate_composed_price($cart_item['composable_products']);
                    $cart_item['data']->set_price($price);

                    // Mark as calculated to prevent re-calculation by other plugins
                    $cart->cart_contents[$cart_item_key]['composable_price_calculated'] = true;
                }
            }
        }

        $already_calculated = true;
    }
}
