<?php

namespace App\Services;

use App\Models\ProductManagement\Product;
use Gloudemans\Shoppingcart\Facades\Cart;

class CartService{


    /** Ce service (classe) permet d'enregister des données en session
     * en utilisant le concept de panier e-commerce.
     * Un avantage principal ici est qu'on peut avoir plusieurs 'paniers'
     * en session : il suffira à chaque fois de nommer "l'instance" qui sera associer
     * Ex: $cart1 = new CartService('cart-1') , $cart2 = new CartService('cart-2')
     */

    public $instance =  CartInstance::DEF;

    public function __construct($instance = CartInstance::DEF) {
        $this->setCartInstance($instance);
    }

    public function setCartInstance($instance){
        $this->instance = $instance;
    }

    /**
     * @return string
     */
    public function getCartInstance(){
        return  $this->instance;
    }

    /**
     * @return mixed
     */
    public function getCart(){
        return Cart::instance($this->getCartInstance());
    }

    /**
     * @param $data
     * @return bool
     */
    public function addItem($data) {
        $id = $data['id'] ?? null;
        if ($id){
            $row =  $this->getContent()->firstWhere('id',$id);
            if ($row) return $this->updateItem($row->rowId,$data);
        }
        return $this->getCart()->add($data);
    }

    /**
     * @param $rowId
     * @param $data
     * @return bool
     */
    public function updateItem($rowId, $data): bool
    {
        $row = $this->getCart()->get($rowId) ;
        if ($row){

            $row = $row->toArray();

            $row['price']       = $data['price'] ?? $row['price'];
            $row['name']        = $data['name'] ?? $row['name'];
            $row['id']          = $data['id'] ?? $row['id'];
            $row['options']['errors'] = null;
            if (isset($data['options']))
                $row['options'] = array_merge($row['options'],$data['options']);

            // dd($row);
            unset($row['rowId']);
            $this->getCart()->update($rowId,$row) ;
            return  true;
        }
        return false;
    }

    /**
     * @param array $rowsIds
     * @return bool
     */
    public function removeItems(array|string $rowsIds): bool
    {
        $success = false;
        if ($rowsIds){
            $rowsIds = is_string($rowsIds) ? [$rowsIds] : $rowsIds;
            foreach ($rowsIds as $rowId) {
                if ($this->getCart()->get($rowId)){
                    $this->getCart()->remove($rowId);
                }
            }
            $success = true;
        }
        return $success;
    }

    /**
     * @param $value
     * @param string $column
     * @return bool
     */
    public function rowExist($value, string $column = "id"): bool
    {
        return in_array($value,$this->getContent()->pluck($column)->toArray());
    }

    /**
     * @param $search
     * @param bool $first
     * @return mixed
     */
    public function getRow($search, bool $first = true): mixed
    {
        if (is_string($search))  return  $this->getCart()->get($search);
        if (is_callable($search)){
            return  $this->getContent()
                        ->filter(fn($item) => $search($item))
                         ->when($first,fn($items) =>$items->first())
                        ;
        }

        return null;
    }

    /**
     * @return mixed
     */
    public function getRowsCount(){
        return $this->getContent()->count();
    }

    /**
     * @return mixed
     */
    public function getContent(){
        return $this->getCart()->content();
    }

    /**
     * @return mixed
     */
    public function destroyCart(){
        return $this->getCart()->destroy();
    }

    public function addToList( $instance, Product $product, $quantity = 1){
        $duplicated = Cart::instance($instance)
                          ->search(function ($cartItem, $rowId) use($product){
                            return $cartItem->id === $product->id;
                        })->first();

        if (!blank($duplicated)) {
          //  throw new Exception(__('Product already exist.'));
            Cart::instance($instance)->update($duplicated->rowId,$duplicated->qty + 1);
            return true;
        } else {
            Cart::instance($instance)
                  ->add($product->id, $product->name, $quantity, $product->price)
                  ->associate(Product::class);
            return true;
        }
    }
}
