<?php

namespace Mnv\Modules\Shop;

use Mnv\Core\Utilities\Cookie\Session;

/**
 * Class Cart
 * @package Mnv\Modules\Shop
 */
class Cart
{
    /** @var string  */
    private string $table  = 'shop_cart';

    /** @var string  */
    private string $primaryKey  = 'cartId';

    /** @var int  */
    public $cartId = 0;

    /** @var array  */
    public $cart = [];


    /** Добавление товара в корзину */
    public function addToCart(int $productId, int $quantity = 1, $options = [], $siteUser = []): bool
    {
        $cart = [
            'userId'    => $siteUser['userId'] ?? 0,
            'productId' => $productId,
            'quantity'  => $quantity,
            'options'   => $options ?? [],
        ];

        if (!Session::has('token_cart_id')) {
            Session::set('token_cart_id', Helpers::createRandomString(20));
        }

        // Товар в корзине
        $this->getCart($cart);
        if (!empty($this->cart)) {
            $cart['cartId'] = $this->cart['cartId'];
            $cart['quantity'] += $this->cart['quantity'];
            return $this->update($cart);
        } else {

            return $this->insert($cart);
        }
    }

    private function insert(array $cart): bool
    {
        // Stock
        if (!$this->hasStockInsert($cart)) {
            return false;
        }

        /** устанавливаем и добавляем в базу session(token) */
        $newOrder = [
            'userId'    => $cart['userId'] ?? 0,
            'productId' => $cart['productId'],
            'options'   => json_encode($cart['options'], JSON_UNESCAPED_UNICODE),
            'quantity'  => $cart['quantity'],
            'token'     => Session::get('token_cart_id'),
            'addedBy'   => gmdate('Y-m-d H:i:s'),
        ];

        if ($this->cartId = connect($this->table)->insert($newOrder)) {
            return true;
        }

        return false;
    }

    public function hasStockInsert($order): bool
    {
        $stock = true;
        $product_query = connect('products')->select('productId, quantity, subtract')->where('productId', $order['productId'])->get('array');
        if ($order['options']) {
            foreach ($order['options'] as $product_option_id => $value) {
                $option_query = connect('product_option')->join('options', 'optionId', '=', 'option_id')->select('product_option_id, product_id, option_id, type, orderBy')->where('product_option_id', $product_option_id)->where('product_id', $product_query['productId'])->get('array');
                if ($option_query) {
                    foreach ($value as $product_option_value_id) {
                        $option_value_query = connect('product_option_value')->join('options', 'optionId', '=', 'option_value_id')->select('option_value_id, quantity, subtract')->where('product_option_value_id', $product_option_value_id)->where('product_option_id', $product_option_id)->get('array');
                        if ($option_value_query) {
                            if ($option_value_query['subtract'] && (!$option_value_query['quantity'] || $option_value_query['quantity'] < $order['quantity'])) {
                                $stock = false;
                            }
                        }
                    }
                }
            }
        }

//        print_r($product_query);
        if (!$product_query['quantity'] || ($product_query['quantity'] < $order['quantity'])) {
            $stock = false;
        }

        return $stock;
    }

    /** Обновление товара в корзине */
    private function update($order): bool
    {
        // Stock
        if (!$this->hasStockUpdate($order[$this->primaryKey], $order['quantity'])) {
            return false;
        }

        if (connect($this->table)
            ->where($this->primaryKey, $order[$this->primaryKey])
            ->where('productId', $order['productId'])
            ->where('options', json_encode($order['options'], JSON_UNESCAPED_UNICODE))
            ->where('token',  Session::get('token_cart_id'))
            ->update(['quantity' => $order['quantity']])) {

            $qty = connect($this->table)->select('quantity')->where($this->primaryKey, $order[$this->primaryKey])->where('token', Session::get('token_cart_id'))->getValue();
            if ($qty == 0) {
                $this->remove($order[$this->primaryKey]);
            }

            return true;
        }

        return false;
    }

    // <----- TODO: готово
    /** обновить кол-во */
    public function updateCountProduct(int $cartId, ?int $quantity): bool
    {
        // Stock
        if (!$this->hasStockUpdate($cartId, $quantity)) {
            return false;
        }
        // Update
        if (connect($this->table)->where($this->primaryKey, $cartId)->where('token', Session::get('token_cart_id'))->update(['quantity' => $quantity])) {
            $qty = connect($this->table)->select('quantity')->where($this->primaryKey, $cartId)->where('token', Session::get('token_cart_id'))->getValue();
            // Remove
            if ($qty == 0) {
                $this->remove($cartId);
            }

            return true;
        }

        return false;
    }
    public function hasStockUpdate($cartId, $quantity): bool
    {
        $stock = true;
        if ($cart = connect()->table('shop_cart')->select('cartId, productId, options, quantity')->where('cartId', $cartId)->where('token', Session::get('token_cart_id'))->get('array')) {
            $product_query = connect('products')->select('productId, quantity, subtract')->where('productId', $cart['productId'])->get('array');
            foreach (json_decode($cart['options'], true) as $product_option_id => $value) {
                $option_query = connect('product_option')->join('options', 'optionId', '=', 'option_id')->select('product_option_id, product_id, option_id, type, orderBy')->where('product_option_id', $product_option_id)->where('product_id', $product_query['productId'])->get('array');
                if ($option_query) {
                    foreach ($value as $product_option_value_id) {
                        $option_value_query = connect('product_option_value')->join('options', 'optionId', '=', 'option_value_id')->select('option_value_id, quantity, subtract')->where('product_option_value_id', $product_option_value_id)->where('product_option_id', $product_option_id)->get('array');
                        if ($option_value_query) {
                            if ($option_value_query['subtract'] && (!$option_value_query['quantity'] || $option_value_query['quantity'] < $quantity)) {
                                $stock = false;
                            }
                        }
                    }
                }
            }

            if (!$product_query['quantity'] || ($product_query['quantity'] < $quantity)) {
                $stock = false;
            }
        }

        return $stock;
    }
    // ---->


    /** удаление 1 товара из корзины */
    public function remove($cartId): bool
    {
        if (connect($this->table)->where($this->primaryKey, $cartId)->where('token',  Session::get('token_cart_id'))->delete()) {
            return true;
        }

        return false;
    }

    /** удаление всех товаров из корзины */
    public function clear(): bool
    {
        if (connect($this->table)->where('token',  Session::get('token_cart_id'))->delete()) {
            return true;
        }

        return false;
    }

    /** получить */
    public function getCart($cart)
    {
//        if (!empty($cart['userId'])) connect()->where('userId', $cart['userId']);
        if (!empty($cart[$this->primaryKey])) connect()->where($this->primaryKey, $cart[$this->primaryKey]);
        if (!empty($cart['productId'])) connect()->where('productId', $cart['productId']);
        if (!empty($cart['options'])) connect()->where('options', json_encode($cart['options'], JSON_UNESCAPED_UNICODE));

        $this->cart = connect($this->table)->select('*')->where('token', Session::get('token_cart_id'))->get('array');
//        print_r(connect()->getQuery());
//        print_r($this->cart);
    }

    /** получить все товары в корзине */
    public function getCarts()
    {
        $this->cart = connect($this->table)->select('*')->where('token', Session::get('token_cart_id'))->getAll('array');
    }


    /** получить кол-во товара в корзине */
    public function getCountProducts()
    {
        return connect($this->table)->sum('quantity', 'count')->where('token',  Session::get('token_cart_id'))->getValue('array');
    }

    /** Общая сумма корзины */
    public function getTotalAmount()
    {
        return connect($this->table)->select('amount')->where('token', Session::get('token_cart_id'))->getValue();
    }


    public function getCartProducts()
    {
        if ($carts = connect()->table('shop_cart')->select('cartId, productId, options, quantity')->where('token', Session::get('token_cart_id'))->getAll('array')) {
            foreach ($carts as $cartId => $cart) {
                $product = connect('products')->select('productId, title, brand, url, special, price, old_price, quantity')->where('productId', $cart['productId'])->get('array');
                $product = prepareProduct($product);
                $carts[$cartId]['cartId']       = $cart['cartId'];
                $carts[$cartId]['productId']    = $product['productId'];
                $carts[$cartId]['title']        = $product['title'];
                $carts[$cartId]['special']      = $product['special'];
                $carts[$cartId]['url']          = $product['url'];
                $carts[$cartId]['price']        = $product['price'];
                $carts[$cartId]['old_price']    = $product['old_price'];
                $carts[$cartId]['qty']          = $product['quantity'];
//                $carts[$cartId]['brand']        = connect('brands')->select('name')->where('fileName', $product['brand'])->getValue();
                $carts[$cartId]['quantity']     = $cart['quantity'];
                $carts[$cartId]['image']        = $product['image'];
//                $total += ($variant['price'] * $cart['quantity']);
//                $count +=  $cart['quantity'];
            }
        }

        return $carts;
    }



    public function getProduct(?int $productId): string
    {
        if ($product = connect('products')->select('productId, sectionId, title')->where('productId', $productId)->get('array')) {
            $product = prepareProduct($product);
            $category = $product['section']['name'] ?? '';

            return $category . ' ' . $product['title'];
        }

        return '';
    }

}