<?php

namespace Soft_Tehnica\Freya_Sync_Service\Services;

class ToppingService
{
    public function __construct()
    {
        $this->register_actions();
    }

    private function register_actions(): void
    {
        add_action('woocommerce_before_add_to_cart_button', [$this, 'display_toppings'], 10);
        add_action('woocommerce_remove_cart_item', [$this, 'remove_toppings_from_cart'], 10, 2);
        add_action('woocommerce_cart_item_restored', [$this, 'on_cart_item_restore'], 10, 2);
        add_filter('woocommerce_add_cart_item_data', [$this, 'add_toppings_to_cart_item'], 10, 2);
        add_filter('woocommerce_cart_item_name', [$this, 'display_toppings_in_cart'], 10, 3);
        add_filter('woocommerce_cart_item_quantity', [$this, 'display_quantity_in_cart'], 10, 3);
        add_filter('woocommerce_checkout_create_order_line_item', [$this, 'add_meta_data_to_order_item'], 10, 4);
        add_action('woocommerce_before_calculate_totals', [$this, 'update_cart_item_prices'], 10, 1);
        add_action('woocommerce_single_product_summary', [$this, 'update_product_summary'], 10);
        add_filter('woocommerce_get_price_html', [$this, 'add_topping_price_div']);

        add_action('wp_ajax_nopriv_fss_get_toppings', [$this, 'get_toppings_for_product']);
        add_action('wp_ajax_fss_get_toppings', [$this, 'get_toppings_for_product']);
    }

    public function add_topping_price_div($price): string
    {
        $price .= ' <span id="fsToppingTotal" class="fss-hide woocommerce-Price-amount amount"></span>';
        return $price;
    }

    /**
     * @ajax fss_get_toppings
     *
     * @return void
     */
    public function get_toppings_for_product(): void
    {
        check_ajax_referer('wp_rest', 'nonce');
        if (!$_REQUEST['id']) {
            wp_send_json_error(null, 400);
            return;
        }

        $product = wc_get_product($_REQUEST['id']);
        if (!$product) {
            wp_send_json_error(null, 404);
            return;
        }

        $toppings = $product->get_meta('freya_sync_toppings', true);
        if (is_array($toppings) && count($toppings) > 0) {
            wp_send_json_success([
                'productPrice' => floatval($product->get_price()),
                'toppings' => $toppings
            ], 200);
            return;
        }

        wp_send_json_error(null, 404);
    }

    public function update_product_summary(): void
    {
        global $post;
        $product = wc_get_product($post->ID);

        $meta_data = $product->get_meta('freya_sync_toppings');
        if (is_array($meta_data) && count($meta_data) > 0) {
            ?>
            <div class='fss-product-topping-info'>
                <?php foreach($meta_data as $meta): ?>
                    <div
                        id="<?php echo $meta['freyaCode'] ?>"
                        class="fss-product-topping fss-hide"
                    >
                        + <?php echo $meta['name']; ?>
                        (<strong>+ <?php echo $meta['price'] ?> lei</strong>)
                    </div>
                <?php endforeach; ?>
            </div>
            <?php
        }
    }

    public function update_cart_item_prices(\WC_Cart $cart): void
    {
        if (is_admin() && !defined('DOING_AJAX')) {
            return;
        }
        if (did_action('woocommerce_before_calculate_totals') >= 2) {
            return;
        }
        foreach ($cart->get_cart() as $cart_item_key => $cart_item) {
            $this->updateToppingCustomPrice($cart_item_key, $cart_item);
            $this->updateToppingQuantities($cart_item_key, $cart_item);
        }
    }

    private function updateToppingCustomPrice(string $cart_item_key, array &$cart_item): void
    {
        if (!isset($cart_item['freya_sync_custom_price']) || !isset($cart_item['freya_sync_is_topping_for'])) {
            return;
        }

        $cart_item['data']->set_price($cart_item['freya_sync_custom_price']);
    }

    private function updateToppingQuantities(string $cart_item_key, array &$cart_item): void
    {
        if (!isset($cart_item['freya_sync_toppings'])) {
            return;
        }

        foreach ($cart_item['freya_sync_toppings'] as $key => $topping) {
            if (count(WC()->cart->get_cart_item($topping['cartKey'])) === 0) {
                unset($cart_item['freya_sync_toppings'][$key]);
                continue;
            }
            WC()->cart->set_quantity($topping['cartKey'], $cart_item['quantity']);
        }
    }

    public function remove_toppings_from_cart($cart_item_key, $cart): void
    {
        $cart_item = $cart->get_cart_item($cart_item_key);
        if (isset($cart_item['freya_sync_toppings'])) {
            $this->remove_toppings_for_item($cart_item);
        }

        if (isset($cart_item['freya_sync_is_topping_for'])) {
            $this->handle_topping_removal($cart_item);
        }
    }

    public function remove_toppings_for_item($cart_item): void
    {
        if (!isset($cart_item['freya_sync_toppings'])) {
            return;
        }

        foreach ($cart_item['freya_sync_toppings'] as $topping) {
            WC()->cart->remove_cart_item($topping['cartKey']);
        }
    }

    public function handle_topping_removal($topping_cart_item): void
    {
        if (!isset($topping_cart_item['freya_sync_is_topping_for'])) {
            return;
        }

        foreach (WC()->cart->cart_contents as &$cart_item) {
            if (!isset($cart_item['freya_sync_topping_parent_code'])) {
                continue;
            }

            $IS_TOPPING_PARENT = $cart_item['freya_sync_topping_parent_code'] === $topping_cart_item['freya_sync_is_topping_for']['uniqueCode'];

            if (!$IS_TOPPING_PARENT) {
                continue;
            }

            if (!isset($cart_item['freya_sync_toppings'])) {
                continue;
            }

            $new_toppings = [];

            foreach ($cart_item['freya_sync_toppings'] as $topping) {
                if ($topping_cart_item['key'] === $topping['cartKey']) {
                    continue;
                }
                $new_toppings[] = $topping;
            }

            if (count($new_toppings) === 0) {
                unset($cart_item['freya_sync_toppings']);
                break;
            }

            $cart_item['freya_sync_toppings'] = $new_toppings;
            break;
        }

        WC()->cart->set_session();
    }

    public function on_cart_item_restore(string $cart_item_key, \WC_Cart $cart): void
    {
        $item = $cart->get_cart_item($cart_item_key);

        if (isset($item['freya_sync_toppings'])) {
            $this->restore_toppings_to_cart($item);
        }

        if (isset($item['freya_sync_is_topping_for'])) {
            $this->handle_topping_restore($item);
        }
    }

    public function restore_toppings_to_cart(array $cart_item): void
    {
        if (!isset($cart_item['freya_sync_toppings'])) {
            return;
        }
        foreach ($cart_item['freya_sync_toppings'] as $topping) {
            WC()->cart->restore_cart_item($topping['cartKey']);
        }
    }

    public function handle_topping_restore(array $cart_item): void
    {
        if (!isset($cart_item['freya_sync_is_topping_for'])) {
            return;
        }

        $topping = wc_get_product($cart_item['product_id']);
        $topping_freya_code = $topping->get_meta('freya_code');

        foreach (WC()->cart->cart_contents as &$item) {
            if (!isset($item['freya_sync_topping_parent_code'])) {
                continue;
            }

            $IS_TOPPING_PARENT = $item['freya_sync_topping_parent_code'] === $cart_item['freya_sync_is_topping_for']['uniqueCode'];

            if (!$IS_TOPPING_PARENT) {
                continue;
            }

            $product = wc_get_product($item['product_id']);

            $product_toppings = $product->get_meta('freya_sync_toppings');

            if (!isset($item['freya_sync_toppings'])) {
                $item['freya_sync_toppings'] = [];
            }

            $meta_topping = null;
            foreach ($product_toppings as $product_topping) {
                if ($product_topping['freyaCode'] === $topping_freya_code) {
                    $meta_topping = $product_topping;
                    break;
                }
            }

            if (!isset($meta_topping)) {
                continue;
            }

            $found = false;

            foreach ($item['freya_sync_toppings'] as $item_topping) {
                if ($item_topping['freyaCode'] === $meta_topping['freyaCode']) {
                    $found = true;
                    break;
                }
            }

            if (!$found) {
                $item['freya_sync_toppings'][] = [
                    'name' => $meta_topping['name'],
                    'freyaCode' => $meta_topping['freyaCode'],
                    'price' => $meta_topping['price'],
                    'cartKey' => $cart_item['key']
                ];
            }
            break;
        }

        WC()->cart->set_session();
    }

    public function add_toppings_to_cart_item($cart_item_data, $product_id)
    {
        $product = wc_get_product($product_id);
        $meta_data = $product->get_meta('freya_sync_toppings');
        if (!$meta_data || !count($meta_data) > 0) {
            return $cart_item_data;
        }

        $uniqueCode = fss_random_string(10);

        foreach ($meta_data as $meta) {
            if (!isset($_POST[$meta['freyaCode']])) {
                continue;
            }

            $products = wc_get_products([
                'meta_key' => 'freya_code',
                'meta_value' => $meta['freyaCode']
            ]);

            if (!isset($products[0])) {
                continue;
            }

            /** @var \WC_Product $topping */
            $topping = $products[0];

            try {
                $key = WC()->cart->add_to_cart($topping->get_id(), $_POST['quantity'] ?? 1, 0, [], [
                    'freya_sync_is_topping_for' => [
                        'uniqueCode' => $uniqueCode
                    ],
                    'freya_sync_custom_price' => $meta['price'],
                ]);

                if (!$key) {
                    continue;
                }

                $cart_item_data['freya_sync_topping_parent_code'] = $uniqueCode;

                if (!isset($cart_item_data['freya_sync_toppings'])) {
                    $cart_item_data['freya_sync_toppings'] = [];
                }

                $cart_item_data['freya_sync_toppings'][] = [
                    'name' => $meta['name'],
                    'price' => $meta['price'],
                    'freyaCode' => $meta['freyaCode'],
                    'cartKey' => $key
                ];
            } catch (\Exception $e) {
                wc_add_notice(
                    'Nu am putut adauga topping-ul' . $meta['name'] . ' in cos. Te rugam sa incerci din nou.',
                    'error'
                );

                continue;
            }
        }

        return $cart_item_data;
    }

    public function add_meta_data_to_order_item($item, $cart_item_key, $values, $order)
    {
        $this->add_toppings_to_order_item($item, $cart_item_key, $values, $order);
        $this->set_topping_parent_for_order_item($item, $cart_item_key, $values, $order);
        $this->set_topping_parent_for_order_item($item, $cart_item_key, $values, $order);

        return $item;
    }

    public function add_toppings_to_order_item(&$item, $cart_item_key, $values, $order)
    {
        if (!isset($values['freya_sync_toppings'])) {
            return $item;
        }

        $meta = [];

        foreach ($values['freya_sync_toppings'] as $topping) {
            $meta[] = [
                'name' => $topping['name'],
                'price' => $topping['price'],
                'freyaCode' => $topping['freyaCode'],
            ];
        }

        $item->add_meta_data('freya_sync_toppings', $meta);
    }

    private function set_topping_parent_for_order_item(&$item, $cart_item_key, $values, $order): void
    {
        if (!isset($values['freya_sync_is_topping_for'])) {
            return;
        }

        $item->add_meta_data('freya_sync_is_topping_for', $values['freya_sync_is_topping_for']);
    }

    private function set_order_items_as_topping_parents(&$item, $cart_item_key, $values, $order): void
    {
        if (!isset($values['freya_sync_topping_parent_code'])) {
            return;
        }

        $item->add_meta_data('freya_sync_topping_parent_code', $values['freya_sync_topping_parent_code']);
    }

    public function display_quantity_in_cart($product_quantity, $cart_item_key, $cart_item): string
    {
        if (isset($cart_item['freya_sync_is_topping_for'])) {
            return "<span class='fss-topping-quantity'>{$cart_item['quantity']}</span>";
        }

        return $product_quantity;
    }

    public function display_toppings_in_cart($name, $cart_item, $cart_item_key): string
    {
        if (isset($cart_item['freya_sync_is_topping_for'])) {
            $parent_code = $cart_item['freya_sync_is_topping_for']['uniqueCode'];

            $parent = null;

            foreach (WC()->cart->get_cart_contents() as $cart_content) {
                if (isset($cart_content['freya_sync_topping_parent_code']) && $cart_content['freya_sync_topping_parent_code'] === $parent_code) {
                    $parent = $cart_content;
                    break;
                }
            }

            if ($parent) {
                $parent_name = $parent['data']->get_name();
                return "<div>$name <span class='fss-topping-label'>(topping pentru {$parent_name})</span></div>";
            }

            return "<div>$name <span class='fss-topping-label'>(topping)</span></div>";
        }

        if (!isset($cart_item['freya_sync_toppings'])) {
            return $name;
        }

        $name .= "<ul class='fss-cart-topping-list'>";

        foreach ($cart_item['freya_sync_toppings'] as $topping) {
            $formatted_price = wc_price($topping['price']);
            $name .= "<li> + {$topping['name']} (+ {$formatted_price})</li>";
        }
        $name .= "</ul>";

        return $name;
    }

    public function display_toppings(): void
    {
        global $post;

        $product = wc_get_product($post->ID);

        $meta_data = $product->get_meta('freya_sync_toppings');
        if (is_array($meta_data) && count($meta_data) > 0) {
            ?>
            <div
                id="FS_TOPPING_PARENT_ID" class="hidden"
                data-id="<?php echo $post->ID ?>"
            >
                <h2 class='fss-product-topping-title'>Topping-uri</h2>
                <?php foreach($meta_data as $topping): ?>
                    <?php
                    woocommerce_form_field(
                        $topping['freyaCode'],
                        array(
                            'type' => 'checkbox',
                            'required' => false,
                            'class' => array('input-checkbox'),
                            'label_class' => array('topping-checkbox'),
                            'label' => "{$topping['name']} (+{$topping['price']} lei)",
                            'id' => "checkbox-{$topping['freyaCode']}"
                        )
                    );
                    ?>
                <?php endforeach; ?>
            </div>
            <?php
        }
    }
}