<?php 
 
 
namespace App\Service; 
 
use App\Document\Coupon; 
 
use App\Document\CouponOverride; 
use App\EventListener\RequestValidation\CheckHeaders; 
use Doctrine\Bundle\MongoDBBundle\ManagerRegistry; 
use Doctrine\Common\Collections\ArrayCollection; 
use Symfony\Component\HttpFoundation\RequestStack; 
 
class CouponManager 
{ 
 
    //services 
    private $request; 
    private $apiCoupon; 
    private $managerRegistry; 
 
    //vars 
    private $coupons; 
    private $currentEmitter; 
    private $overrideCoupons; 
 
    private $cart = []; 
 
    public function __construct(RequestStack $requestStack, APIDigitalCouponHTTP $apiCoupon, ManagerRegistry $managerRegistry) 
    { 
        $this->request = $requestStack->getCurrentRequest(); 
        $this->apiCoupon = $apiCoupon; 
        $this->managerRegistry = $managerRegistry; 
 
        $this->currentEmitter = $this->request->headers->get(CheckHeaders::SOGEC_HEADER_EMITTER_CODE_NAME); 
        $this->apiCoupon->setCodeDemandeur($this->currentEmitter); 
        $this->coupons = $this->apiCoupon->getCoupponByMedia(); 
        $this->overrideCoupons(); 
    } 
 
    public function getCart() :array 
    { 
        return $this->cart; 
    } 
 
    public function getCartItemQuantity(Coupon $coupon) :int 
    { 
        return $opCode[$coupon->getOperationCode()]['quantity'] ?? 0; 
    } 
 
    public function addToCart(Coupon $coupon, $nb = 1) :self 
    { 
        $opCode = $coupon->getOperationCode(); 
        if( !isset( $this->cart[$opCode] ) ) { 
            $this->cart[$opCode]["quantity"] = 0; 
            $this->cart[$opCode]["item"] = $coupon; 
        } 
 
        $this->cart[$opCode]["quantity"] += $nb; 
        $this->cart[$opCode]["item"] = $coupon; 
        $this->decreaseStock($coupon, $nb); 
 
        return $this; 
    } 
 
    public function clearCart() :self 
    { 
        if( is_array($this->cart) ) { 
            foreach($this->cart as $item) { 
                $quantity = $item["quantity"] ?? 0; 
                $coupon = $item["item"] ?? null; 
 
                if( $quantity <= 0 || !$coupon instanceof Coupon) { 
                    continue; 
                } 
                $this->increaseStock($coupon, $quantity); 
            } 
        } 
        return $this; 
    } 
 
    public function geCollection(): array 
    { 
        return $this->overrideCoupons ?? []; 
    } 
 
    public function getItem(string $couponCode): ?Coupon 
    { 
 
        if(!$this->overrideCoupons instanceof ArrayCollection) { 
            $this->overrideCoupons = new ArrayCollection($this->overrideCoupons); 
        } 
 
        $coupon = $this->overrideCoupons 
            ->filter( 
                function (Coupon $coupon) use ($couponCode) { 
                    return $coupon->getOperationCode() === $couponCode; 
                } 
            )->first(); 
 
        if(!$coupon instanceof Coupon) { 
            return null; 
        } 
 
        return $coupon; 
    } 
 
    private function overrideCoupons(): self 
    { 
        $this->overrideCoupons = []; 
        $repo = $this->managerRegistry->getRepository(CouponOverride::class); 
 
        foreach( $this->coupons as $key => $coupon ) { 
 
            $overrideCoupon = $repo->findOneBy(['operationCode' => $coupon->getOperationCode()]); 
            // rm coupon if no config 
            if (!$overrideCoupon instanceof CouponOverride) { 
                continue; 
            } 
 
            $stock = min( 
                (int)$overrideCoupon->getStock($this->currentEmitter)->getCurrent(), 
                (int)$overrideCoupon->getCurrentGlobalStock(), 
                (int)$coupon->getStock() 
            ); 
            $coupon->setStock($stock); 
            $this->overrideCoupons[] = $coupon; 
        } 
        return $this; 
    } 
 
    private function decreaseStock(Coupon $coupon, $nb = 1) 
    { 
        $repo = $this->managerRegistry->getRepository(CouponOverride::class); 
        $overrideCoupons = $repo->findOneBy(["operationCode" => $coupon->getOperationCode()]); 
        if( !$overrideCoupons instanceof CouponOverride) { 
            return; 
        } 
        $repo = $this->managerRegistry->getRepository(CouponOverride::class); 
        $repo->decreaseStock($coupon->getOperationCode(), $this->currentEmitter, $nb); 
    } 
 
    private function increaseStock(Coupon $coupon, $nb = 1) 
    { 
        $repo = $this->managerRegistry->getRepository(CouponOverride::class); 
        $overrideCoupons = $repo->findOneBy(["operationCode" => $coupon->getOperationCode()]); 
        if( !$overrideCoupons instanceof CouponOverride) { 
            return; 
        } 
        $repo = $this->managerRegistry->getRepository(CouponOverride::class); 
        $repo->increaseStock($coupon->getOperationCode(), $this->currentEmitter, $nb); 
    } 
}