<?php

/*
 * kohinos_cooperatic
 * Copyright (C) 2019-2020  ADML63
 * Copyright (C) 2020- Cooperatic
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
namespace App\Listener;

use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;

/**
 * Class AfterLoginRedirection
 *
 * @package App\AppListener
 */
class AfterLoginRedirection implements AuthenticationSuccessHandlerInterface
{
    private $router;
    private $em;
    private $tokenStorage;

    /**
     * AfterLoginRedirection constructor.
     *
     * @param RouterInterface $router
     */
    public function __construct(RouterInterface $router, EntityManagerInterface $em, TokenStorageInterface $tokenStorage)
    {
        $this->router = $router;
        $this->em = $em;
        $this->tokenStorage = $tokenStorage;
    }

    /**
     * @param Request        $request
     *
     * @param TokenInterface $token
     *
     * @return RedirectResponse
     */
    public function onAuthenticationSuccess(Request $request, TokenInterface $token)
    {
        $roles = $token->getRoles();
        $user = $token->getUser();
        $groups = $token->getUser()->getGroups();
        $possibleGroups = $token->getUser()->getPossibleGroups();

        $rolesTab = array_map(function ($role) {
            return $role->getRole();
        }, $roles);

        $request->getSession()->remove('_prestagere');
        $request->getSession()->remove('_comptoirgere');
        $request->getSession()->remove('_groupegere');
        if ($user->getPossiblegroups()->count() == 1) {
            if ($user->getGroups()->count() != 1) {
                $groupe = $user->getPossiblegroups()->first();
                if (in_array('ROLE_PRESTATAIRE', $groupe->getRoles()) && count($user->getPrestataires()) >= 1) {
                    $request->getSession()->set('_prestagere', $user->getPrestataires()[0]);
                } elseif (in_array('ROLE_CAISSIER_PRESTATAIRE', $groupe->getRoles()) && count($user->getCaissierprestataires()) >= 1) {
                    $request->getSession()->set('_prestagere', $user->getCaissierprestataires()[0]);
                } elseif (in_array('ROLE_COMPTOIR', $groupe->getRoles()) && count($user->getComptoirsGeres()) >= 1) {
                    $request->getSession()->set('_comptoirgere', $user->getComptoirsGeres()[0]);
                } elseif (in_array('ROLE_CAISSIER_COMPTOIR', $groupe->getRoles()) && count($user->getCaissiercomptoirs()) >= 1) {
                    $request->getSession()->set('_comptoirgere', $user->getCaissiercomptoirs()[0]);
                } elseif ((in_array('ROLE_TRESORIER', $groupe->getRoles()) || in_array('ROLE_CONTACT', $groupe->getRoles()) || in_array('ROLE_GESTION_GROUPE', $groupe->getRoles())) && count($user->getGroupesGeres()) >= 1) {
                    $request->getSession()->set('_groupegere', $user->getGroupesGeres()[0]);
                }
                $user->setGroups([$groupe]);
                $this->em->persist($user);
                $this->em->flush();
                $this->updateToken($user);
            } else {
                $groupe = $user->getGroups()->first();
                if (in_array('ROLE_PRESTATAIRE', $groupe->getRoles()) && count($user->getPrestataires()) >= 1) {
                    $request->getSession()->set('_prestagere', $user->getPrestataires()[0]);
                } elseif (in_array('ROLE_CAISSIER_PRESTATAIRE', $groupe->getRoles()) && count($user->getCaissierprestataires()) >= 1) {
                    $request->getSession()->set('_prestagere', $user->getCaissierprestataires()[0]);
                } elseif (in_array('ROLE_COMPTOIR', $groupe->getRoles()) && count($user->getComptoirsGeres()) >= 1) {
                    $request->getSession()->set('_comptoirgere', $user->getComptoirsGeres()[0]);
                } elseif (in_array('ROLE_CAISSIER_COMPTOIR', $groupe->getRoles()) && count($user->getCaissiercomptoirs()) >= 1) {
                    $request->getSession()->set('_comptoirgere', $user->getCaissiercomptoirs()[0]);
                } elseif ((in_array('ROLE_TRESORIER', $groupe->getRoles()) || in_array('ROLE_CONTACT', $groupe->getRoles()) || in_array('ROLE_GESTION_GROUPE', $groupe->getRoles())) && count($user->getGroupesGeres()) >= 1) {
                    $request->getSession()->set('_groupegere', $user->getGroupesGeres()[0]);
                }
            }
        } elseif (count($user->getPossiblegroups()) > 1) {
            if ($user->getGroups()->count() != 1) {
                $hasSuperAdminRole = false;
                foreach ($user->getPossiblegroups() as $groupe) {
                    if (in_array('ROLE_SUPER_ADMIN', $groupe->getRoles())) {
                        $hasSuperAdminRole = true;
                        $user->setGroups([]);
                        $this->em->persist($user);
                        $this->em->flush();
                        $user->setGroups([$groupe]);
                        $this->em->persist($user);
                        $this->em->flush();
                        $this->updateToken($user);
                    }
                }
                if (!$hasSuperAdminRole) {
                    $user->setGroups([]);
                    $user->setRoles(['ROLE_USER']);
                    $this->em->persist($user);
                    $this->em->flush();
                    $this->updateToken($user);
                }
            } else {
                $groupe = $user->getGroups()->first();
                if (in_array('ROLE_PRESTATAIRE', $groupe->getRoles()) && count($user->getPrestataires()) >= 1) {
                    $request->getSession()->set('_prestagere', $user->getPrestataires()[0]);
                } elseif (in_array('ROLE_CAISSIER_PRESTATAIRE', $groupe->getRoles()) && count($user->getCaissierprestataires()) >= 1) {
                    $request->getSession()->set('_prestagere', $user->getCaissierprestataires()[0]);
                } elseif (in_array('ROLE_COMPTOIR', $groupe->getRoles()) && count($user->getComptoirsGeres()) >= 1) {
                    $request->getSession()->set('_comptoirgere', $user->getComptoirsGeres()[0]);
                } elseif (in_array('ROLE_CAISSIER_COMPTOIR', $groupe->getRoles()) && count($user->getCaissiercomptoirs()) >= 1) {
                    $request->getSession()->set('_comptoirgere', $user->getCaissiercomptoirs()[0]);
                } elseif ((in_array('ROLE_TRESORIER', $groupe->getRoles()) || in_array('ROLE_CONTACT', $groupe->getRoles()) || in_array('ROLE_GESTION_GROUPE', $groupe->getRoles())) && count($user->getGroupesGeres()) >= 1) {
                    $request->getSession()->set('_groupegere', $user->getGroupesGeres()[0]);
                }
            }
        }

        if (in_array('ROLE_SUPER_ADMIN', $rolesTab, true)) {
            // c'est un administrateur
            $redirection = new RedirectResponse($this->router->generate('sonata_admin_dashboard'));
        } else {
            $redirection = new RedirectResponse($this->router->generate('index'));
        }

        return $redirection;
    }

    private function updateToken($user)
    {
        $token = new UsernamePasswordToken($user, $user->getPassword(), 'main', $user->getRoles());
        $this->tokenStorage->setToken($token);
    }
}
