<?php

namespace App\Utils;

use App\Entity\AccountAdherent;
use App\Entity\AccountComptoir;
use App\Entity\AccountGroupe;
use App\Entity\AccountPrestataire;
use App\Entity\AccountSiege;
use App\Entity\Adherent;
use App\Entity\Comptoir;
use App\Entity\OperationAdherent;
use App\Entity\OperationComptoir;
use App\Entity\OperationGroupe;
use App\Entity\OperationPrestataire;
use App\Entity\OperationSiege;
use App\Entity\Prestataire;
use App\Entity\Siege;
use App\Enum\CurrencyEnum;
use App\Flux\AccountInterface;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository;
use FOS\UserBundle\Model\UserInterface;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Security\Core\Security;

class OperationUtils
{
    private $em;
    private $session;
    private $security;

    public function __construct(EntityManagerInterface $em, SessionInterface $session, Security $security)
    {
        $this->em = $em;
        $this->session = $session;
        $this->security = $security;
    }

    private function getQueryOperations(EntityRepository $repo, AccountInterface $account)
    {
        return $repo
            ->createQueryBuilder('a')
            ->addSelect('flux')
            ->leftJoin('a.flux', 'flux')
            ->where('a.account = :account')
            ->setParameter('account', $account->getId())
            ->orderBy('a.createdAt', 'DESC')
            ->getQuery();
    }

    public function getCurrentAccountable(UserInterface $user)
    {
        if (null != $this->session->get('_prestagere') && ($user->isGranted('ROLE_PRESTATAIRE') || $user->isGranted('ROLE_CAISSIER'))) {
            return $this->session->get('_prestagere');
        } elseif (null != $user->getAdherent() && $user->isGranted('ROLE_ADHERENT')) {
            return $user->getAdherent();
        } elseif (null != $this->session->get('_comptoirgere') && $user->isGranted('ROLE_COMPTOIR')) {
            return $this->session->get('_comptoirgere');
        } elseif (null != $this->session->get('_groupegere') && $user->isGranted('ROLE_GESTION_GROUPE')) {
            return $this->session->get('_groupegere');
        } elseif ($user->isGranted('ROLE_ADMIN_SIEGE')) {
            $siege = $this->em->getRepository(Siege::class)->findOneById(1);

            return $siege;
        }

        return null;
    }

    /**
     * @return Account[] Returns an array of Account objects
     */
    public function getUserOperationsByCurrency(string $currency = null)
    {
        if (null == $this->security->getUser()) {
            return null;
        }
        $object = $this->getCurrentAccountable($this->security->getUser());
        $repo = null;
        $account = null;
        if ($object instanceof Prestataire) {
            $account = $this->em->getRepository(AccountPrestataire::class)->findOneBy(['prestataire' => $object, 'currency' => CurrencyEnum::CURRENCY_EMLC]);
            $repo = $this->em->getRepository(OperationPrestataire::class);
        } elseif ($object instanceof Adherent) {
            $account = $this->em->getRepository(AccountAdherent::class)->findOneBy(['adherent' => $object, 'currency' => CurrencyEnum::CURRENCY_EMLC]);
            $repo = $this->em->getRepository(OperationAdherent::class);
        } elseif ($object instanceof Groupe) {
            $account = $this->em->getRepository(AccountGroupe::class)->findOneBy(['groupe' => $object, 'currency' => CurrencyEnum::CURRENCY_MLC]);
            $repo = $this->em->getRepository(OperationGroupe::class);
        } elseif ($object instanceof Comptoir) {
            $account = $this->em->getRepository(AccountComptoir::class)->findOneBy(['comptoir' => $object, 'currency' => CurrencyEnum::CURRENCY_MLC]);
            $repo = $this->em->getRepository(OperationComptoir::class);
        } elseif ($object instanceof Siege) {
            if (null != $currency) {
                if (!in_array($currency, CurrencyEnum::getAvailableTypes())) {
                    throw new \Exception('Opération impossible ! Type de currency  ' . $currency . ' inexistant');
                }
                $account = $object->getAccountWithCurrency($currency);
            } else {
                $account = $this->em->getRepository(AccountSiege::class)->findOneBy(['siege' => $object, 'currency' => CurrencyEnum::CURRENCY_MLC]);
            }
            $repo = $this->em->getRepository(OperationSiege::class);
        }
        if (null == $repo || null == $account) {
            return null;
        }

        return $this->getQueryOperations($repo, $account);
    }
}
