<?php

namespace Lc\ShopBundle\Services ;

use Doctrine\ORM\EntityManagerInterface;
use Lc\ShopBundle\Context\CreditHistoryInterface;
use Lc\ShopBundle\Context\MerchantInterface;
use Lc\ShopBundle\Context\MerchantUtilsInterface;
use Lc\ShopBundle\Context\UserInterface;
use Lc\ShopBundle\Context\UserMerchantInterface;
use Lc\ShopBundle\Model\CreditHistory;
use Symfony\Component\Security\Core\Security;

class CreditUtils
{
        protected $em ;
        protected $security ;
        protected $merchantUtils ;
        protected $userMerchantRepository ;

        public function __construct(EntityManagerInterface $em, Security $security, MerchantUtilsInterface $merchantUtils)
        {
                $this->em = $em ;
                $this->security = $security ;
                $this->merchantUtils = $merchantUtils ;
                $this->userMerchantRepository = $this->em->getRepository($this->em->getClassMetadata(UserMerchantInterface::class)->getName()) ;
        }

        public function getUserMerchant(UserInterface $user = null, MerchantInterface $merchant = null)
        {
                if(!$user) {
                        $user = $this->security->getUser() ;
                }

                $merchant = $this->getMerchant($merchant) ;

                $userMerchant = $this->userMerchantRepository->findOneBy([
                        'user' => $user,
                        'merchant' => $merchant
                ]) ;
                return $userMerchant ;
        }

        public function createUserMerchant(UserInterface $user, MerchantInterface $merchant = null)
        {
                $merchant = $this->getMerchant($merchant) ;
                $classUserMerchant = $this->em->getClassMetadata(UserMerchantInterface::class)->getName();

                $userMerchant = new $classUserMerchant ;
                $userMerchant->setUser($user) ;
                $userMerchant->setMerchant($merchant) ;
                $userMerchant->setCredit(0) ;
                $userMerchant->setCreditActive(true) ;

                $this->em->persist($userMerchant) ;
                $this->em->flush() ;

                return $userMerchant ;
        }

        public function updateCreditActive($user = null, $merchant = null, $creditActive = true)
        {
                if(!$user) {
                        $user = $this->security->getUser() ;
                }

                $userMerchant = $this->getUserMerchant($user, $merchant) ;
                if(!$userMerchant) {
                        $userMerchant = $this->createUserMerchant($user, $merchant) ;
                }

                $userMerchant->setCreditActive($creditActive) ;

                $this->em->persist($userMerchant) ;
                $this->em->flush() ;

                return $userMerchant ;
        }

        public function activeCredit($user = null, $merchant = null)
        {
                return $this->updateCreditActive($user, $merchant, true) ;
        }

        public function unactiveCredit($user = null, $merchant = null)
        {
                return $this->updateCreditActive($user, $merchant, false) ;
        }


        public function isCreditActiveByUser(UserInterface $user, MerchantInterface $merchant = null){
                $userMerchant = $this->getUserMerchant($user, $merchant);

                return $this->isCreditActive($userMerchant);
        }

        public function isCreditActive(UserMerchantInterface $userMerchant = null){

                if(!$userMerchant || ($userMerchant && !$userMerchant->isCreditActive())) {
                        return false ;
                }

                return true ;
        }

        public function isCreditSufficientToPay($userMerchant, $amount)
        {
                if($this->isCreditActive($userMerchant) && $userMerchant->getCredit() >= $amount) {
                        return true ;
                }

                return false;
        }

        public function createCreditHistory($type, $user, $params = [])
        {
                $creditHistory = $this->initCreditHistory($type, $user, $params) ;
                return $this->saveCreditHistory($creditHistory) ;
        }

        public function initCreditHistory($type, $user, $params = [])
        {
                $merchant = isset($params['merchant']) ? $params['merchant'] : null ;
                $userMerchant = $this->getUserMerchant($user, $merchant) ;
                $isCreditActive = $this->isCreditActive($userMerchant) ;

                if($isCreditActive) {
                        $amount = isset($params['amount']) ? $params['amount'] : null ;
                        $meanPayment = isset($params['meanPayment']) ? $params['meanPayment'] : null ;
                        $reference = isset($params['reference']) ? $params['reference'] : null ;
                        $comment = isset($params['comment']) ? $params['comment'] : null ;
                        $orderPayment = isset($params['orderPayment']) ? $params['orderPayment'] : null ;
                        $orderRefund = isset($params['orderRefund']) ? $params['orderRefund'] : null ;

                        // credit history
                        $classCreditHistory = $this->em->getClassMetadata(CreditHistoryInterface::class)->getName();

                        $creditHistory = new $classCreditHistory ;
                        $creditHistory->setType($type) ;
                        $creditHistory->setUserMerchant($userMerchant) ;
                        $creditHistory->setAmount($amount) ;
                        $creditHistory->setMeanPayment($meanPayment) ;
                        $creditHistory->setReference($reference) ;
                        $creditHistory->setComment($comment) ;
                        $creditHistory->setOrderPayment($orderPayment) ;
                        $creditHistory->setOrderRefund($orderRefund) ;

                        return $creditHistory ;
                }

                return false ;
        }

        public function saveCreditHistory($creditHistory)
        {
                if($creditHistory) {
                        $userMerchant = $creditHistory->getUserMerchant() ;
                        $isCreditActive = $this->isCreditActive($userMerchant) ;

                        if($isCreditActive) {
                                if($creditHistory->getType() == CreditHistory::TYPE_CREDIT) {
                                        $userMerchantAmount = $userMerchant->getCredit() + $creditHistory->getAmountInherited() ;
                                        $this->updateCredit($userMerchant,$creditHistory, $userMerchantAmount);
                                        return true;
                                }elseif($creditHistory->getType() == CreditHistory::TYPE_DEBIT) {
                                        if ($this->isCreditSufficientToPay($userMerchant, $creditHistory->getAmountInherited())) {
                                                $userMerchantAmount = $userMerchant->getCredit() - $creditHistory->getAmountInherited();
                                                $this->updateCredit($userMerchant,$creditHistory, $userMerchantAmount);
                                                return true;
                                        } else {
                                                return false;
                                        }
                                }
                        }
                }

                return false ;
        }

        public function updateCredit($userMerchant, $creditHistory, $amount)
        {
                $this->em->persist($creditHistory) ;
                $userMerchant->setCredit($amount) ;
                $this->em->persist($userMerchant) ;
                $this->em->flush() ;
                return $userMerchant;
        }

        public function getMerchant($merchant)
        {
                if(!$merchant) {
                        $merchant = $this->merchantUtils->getMerchantCurrent() ;
                }

                return $merchant ;
        }
}