<?php

namespace Clevercherry\Backslash4\Traits;


use Illuminate\Http\Request;
use Illuminate\Support\Facades\Session;

trait cartControl
{
    //order and wishlist overrides this
    //public static $cartName = 'cart';

    /**
     * Add an item to the basket
     * You may wan to overide this basic functionality in your app
     */
    public function amendBasket(Request $request)
    {
        
        if($request->action=='add-qty')
            return $this->addToBasket($request);
        
        if($request->action=='set-qty')
            return $this->setBasketQty($request);
        
        return [];
    }

    /**
     * set the qty on a line item in the cart
     * if that line item does not exist, do nothing
     */
    public function setBasketQty(Request $request)
    {
        $id = $request->lineid;
        if(empty($id))
            $id = $request->id;
        
        $options =  static::getOptionsFromRequest($request); 

        $qty = $request->qty;

        $cart = self::getCalcCart();

        $found=null;
        foreach($cart['items'] as $key => $line)
        {
            if( ($line['id']==$id) && ($line['options']===$options) )
            {   $found = $key;
                break;
            }
        }

        if($found===null) {
            return $this->addToBasket($request);
        }
        
        //else

        if($qty==0 || $qty=='0')
            unset($cart['items'][$found]);
        else
            $cart['items'][$found]['qty']=$qty;
        
        $cart = self::getCalcCart($cart);

        self::saveCart($cart);
        
        return $cart;
    }

    /**
     * Add an item to the basket
     * You may want to ovveride this basic functionality in your app
     */
    public function addToBasket(Request $request)
    {
        $id = $request->id;
        if(empty($id))
            $id = $request->lineid;
        $qty = $request->qty;
        $price = $request->price ?? 0; //pennies

        //data for options - application dependant - optional
        $options =  static::getOptionsFromRequest($request); //default @$request->options; 

        //1. add it to the SESSION
        $cart = self::getCalcCart();
        if(empty($cart) || !isset($cart['items']) || empty($cart['items']))
        {
            $cart['items']=[];
            $cart['items'][$id] = ['id' => $id, 'qty' => $qty, 'price' => $price, 'options' => $options];
        } else
        {
            $found=null;
            foreach($cart['items'] as $key => $line)
                if( ($line['id']==$id) && ($line['options']===$options) )
                {   $found = $key;
                    break;
                }

            if($found!==null)
                $cart['items'][$found]['qty'] += $qty;
            else
                $cart['items'][] = ['id' => $id, 'qty' => $qty, 'price' => $price, 'options' => $options];
        }
        $cart = self::getCalcCart($cart);
        self::saveCart($cart);

        return $cart;
    }

    /**
     * You may will want to implment this in your model to also save to the model
     * see order and wishlist
     * Both standard backslash4 implementations (order and wishlist) implement this function
     * you can of course override it in your app so that it only does the below and stores in the session
     */
    abstract public static function saveCart($cart = null);
    /*
    {
        //this may seem pointless but if no cart exists it will create it
        if(empty($cart))
            $cart = self::getCalcCart();

        //in your model add save functionality
        //see order and wishlist
        
        self::putCart($cart);
    }
    */

    /**
     * Yes it only does one thing but it does it with the cartname (self::$cartName)
     */
    public static function putCart($cart)
    {        
        Session::put(self::$cartName, $cart);
    }
    
    public static function setShipping($carrier=null, $shipping, $cart = null)
    {
        if(empty($cart))
            $cart = self::getCalcCart($cart=null);
        
        if($carrier!=null)
            $cart['carrier']=$carrier;
        
        $cart['shipping']=$shipping;

        $cart = self::getCalcCart($cart);
        self::saveCart($cart);
    }

    /**
     * overload this function in your app to json decocde anything you need to
     * tidy up the options for the cart
     */
    public static function getOptionsFromRequest(Request $request) : object | array | string | null
    {
        return  empty(@$request->options) ? null : $request->options ;
    }

    
    public static function forgetCart()
    {
        Session::forget(self::$cartName);
    }

    public static function getCalcCart($cart=null) : Array
    {
        if(empty($cart))
            $cart = Session::get(self::$cartName);

        if(!isset($cart['shipping']))
            $cart['shipping']=0;
        
        $cart['total_nett'] = 0;
        $cart['total_gross'] = 0;
        $cart['total_items'] = 0;
        if(empty($cart) || !isset($cart['items']) || empty($cart['items']))
            $cart['items']=[];
        
        foreach($cart['items'] as $key => $line)
        {
            if($line['qty']<=0)
                unset($cart['items'][$key]);
            else
            {   $cart['total_nett'] += ($line['qty'] * $line['price']);
                $cart['total_gross'] += ($line['qty'] * $line['price']);
                $cart['total_items'] += $line['qty'];
            }
        }

        $cart['total_nett'] += (int) $cart['shipping'];

        return $cart;
    }

    /**
     * get the item line from the cart, matching id (which may have a prefix like the maodel path and a colon)
     * 
     */
    public static function getCartItem($key, $options=null, $prefix='')
    {
        $cart = self::getCalcCart();
        $fullkey = $key;
        if(!empty($prefix))
            $fullkey = $prefix . ':' . $key;
        
        if(empty($options))
        {
            foreach($cart['items'] as $linekey => $line)
            {
                if($line['id']==$fullkey)
                    return $line;
            }
        } else
        {
            foreach($cart['items'] as $linekey => $line)
            {
                if(($line['id']==$fullkey) && ($line['options']==$options))
                    return $line;
            }
        }
        
        return null;
    }

    public static function getCartItemQty($key, $options=null, $prefix='', $default=0) : int | float
    {
        $line = self::getCartItem($key, $options, $prefix);
        if(empty($line) || !isset($line['qty']) || $line['qty']===null || $line['qty']==='')
            return $default;

        //else
        return floatval($line['qty']);
    }
    
    
    public static function isCartEmpty() : bool
    {
        $cart = Session::get(self::$cartName);
        return (empty($cart) 
                    || !isset($cart['items']) || empty($cart['items']) 
                    || !isset($cart['total_items']) || empty($cart['total_items']) );
    }
}