<?php

namespace AppBundle\Controller\Admin;

use AppBundle\Entity\Company;
use AppBundle\Entity\User;
use AppBundle\Enum\OperationITDLCType;
use AppBundle\Enum\UserType;
use AppBundle\Form\Type\UserFormType;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Query;
use Doctrine\ORM\Tools\Pagination\Paginator;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Translation\TranslatorInterface;

class UserController extends Controller
{
    /**
     * @var EntityManagerInterface
     */
    private $em;

    /**
     * @var SessionInterface
     */
    private $session;

    /**
     * @var TranslatorInterface
     */
    private $translator;
    
    public function __construct(
        EntityManagerInterface $em,
        SessionInterface $session,
        TranslatorInterface $translator
    )
    {
        $this->em = $em;
        $this->session = $session;
        $this->translator = $translator;
    }

    /**
     * Liste des utilisateurs (mélangés ou filtrés par type)
     *
     * @Route(
     *      "/users/list/{type}/{page}",
     *      requirements = {"page": "\d+"},
     *      name = "admin_list_user"
     * )
     *
     * @param Request $request
     * @param string $type
     * @param int $page
     * @return Response
     */
    public function indexAction (Request $request, string $type = 'all', int $page = 1)
    {
        $academies = array();
        $academy = $request->get('academy');
        $companies = array();
        $company = $request->get('company');
        $lastname = $request->get('lastname');
        $firstname = $request->get('firstname');
        $username = $request->get('username');
        $email = $request->get('email');

        $resultsMaxPerPage = $this->getParameter('results.admin.max_per_page');
        $firstresult = ($page - 1) * $resultsMaxPerPage;

        // Création de la requête DQL en fonction du type d'utilisateur à afficher ainsi que des filtres utilisés
        $qbUsers = $this->em->createQueryBuilder();
        $qbUsers
            ->select('u')
            ->from(User::class, 'u')
            ->where($qbUsers->expr()->not($qbUsers->expr()->like('u.username', ':u_username')))
            ->andWhere($qbUsers->expr()->isNotNull('u.firstname'))
            ->andWhere($qbUsers->expr()->isNotNull('u.lastname'))
            ->andWhere('u.username <> :u_username2')
            ->orderBy('u.created', 'desc')
            ->addOrderBy('u.id', 'desc')
            ->setParameters(array(
                'u_username' => 'admin%',
                'u_username2' => '.abstrakt',
            ))
            ->setFirstResult($firstresult)
            ->setMaxResults($resultsMaxPerPage);

        switch ($type) {
            case UserType::TEACHER:
                $qbUsers
                    ->andWhere('u.type = :u_type')
                    ->setParameter('u_type', UserType::TEACHER);
                if ($academy) {
                    $qbUsers
                        ->andWhere('u.academy = :u_academy')
                        ->setParameter('u_academy', $academy);
                }

                // Récupération de la liste des académies
                $academies = $this->em->getRepository(User::class)->findAcademies(Query::HYDRATE_ARRAY);
                break;

            case UserType::ENGINEER:
                $qbUsers
                    ->leftJoin('u.establishment', 'e')
                    ->andWhere('u.type = :u_type')
                    ->setParameter('u_type', UserType::ENGINEER);
                if ($company) {
                    $qbUsers
                        ->andWhere('e.name = :e_name')
                        ->setParameter('e_name', $company);
                }

                // Récupération de la liste des entreprises
                $companies = $this->em->getRepository(Company::class)->findBy([], ['name' => 'ASC']);
                break;

            default:    // 'all' === $type
                if ($lastname) {
                    $qbUsers
                        ->andWhere($qbUsers->expr()->like(
                            $qbUsers->expr()->upper('u.lastname'),
                            $qbUsers->expr()->upper(':u_lastname')
                        ))
                        ->setParameter('u_lastname', "%".$lastname."%");
                }
                if ($firstname) {
                    $qbUsers
                        ->andWhere($qbUsers->expr()->like(
                            $qbUsers->expr()->upper('u.firstname'),
                            $qbUsers->expr()->upper(':u_firstname')
                        ))
                        ->setParameter('u_firstname', "%".$firstname."%");
                }
                if ($username) {
                    $qbUsers
                        ->andWhere($qbUsers->expr()->like(
                            $qbUsers->expr()->upper('u.username'),
                            $qbUsers->expr()->upper(':u_username_search')
                        ))
                        ->setParameter('u_username_search', "%".$username."%");
                }
                if ($email) {
                    $qbUsers
                        ->andWhere($qbUsers->expr()->like(
                            $qbUsers->expr()->upper('u.email'),
                            $qbUsers->expr()->upper(':u_email')
                        ))
                        ->setParameter('u_email', "%".$email."%");
                }
                break;
        }

        // Constructeur pagination
        $users = new Paginator($qbUsers);

        // Mise à jour de la session avec les nouvelles valeurs
        $session_settings_new['academy'] = $academy;
        $session_settings_new['company'] = $company;
        $session_settings_new['firstname'] = $firstname;
        $session_settings_new['lastname'] = $lastname;
        $session_settings_new['username'] = $username;
        $session_settings_new['email'] = $email;
        $this->session->set($request->get('_route'), $session_settings_new);

        return $this->render('Admin/User/index.html.twig', array(
            'academies' => $academies,
            'academy_selected' => $academy,
            'companies' => $companies,
            'company_selected' => $company,
            'firstname' => $firstname,
            'lastname' => $lastname,
            'username' => $username,
            'email' => $email,
            'pageactuelle' => $page,
            'nb_pages' => ceil(count($users) / $resultsMaxPerPage),
            'type' => $type,
            'users' => $users,
        ));
    }

    /**
     * Edition de la page d'un utilisateur (professeur ou ingénieur).
     * Liste les demandes et opérations ITDLC, ainsi que les demandes PEE pour les professeurs
     *
     * @Route(
     *      "/users/edit/{user}",
     *      requirements = {"user": "\d+"},
     *      name = "admin_user_edit"
     * )
     *
     * @param Request $request
     * @param User $user
     * @return \Symfony\Component\HttpFoundation\RedirectResponse|Response
     */
    public function editAction(Request $request, User $user)
    {
       
        $demandespee = null;

        if (UserType::TEACHER == $user->getType()) {
            // Demandes PEE
            $querydemandepee = $this->em
                ->createQuery(
                    "SELECT d
                    FROM AppBundle:DemandePEE d
                    WHERE d.cuser=:iduser
                    ORDER BY
                    d.created DESC,
                    d.id DESC"
                )
                ->setParameter('iduser', $user->getId());
            $demandespee = $querydemandepee->getResult();

            // Demandes ITDLC
            $querydemandeitdlc = $this->em
                ->createQuery(
                    "SELECT d
                    FROM AppBundle:OperationITDLC d
                    WHERE
                    d.prof = :d_prof
                    AND d.type = :d_type
                    ORDER BY
                    d.created DESC,
                    d.id DESC"
                )
                ->setParameters(array(
                    'd_prof' => $user->getId(),
                    'd_type' => OperationITDLCType::DEMANDE,
                ));
            $demandesitdlc = $querydemandeitdlc->getResult();

            // Opérations ITDLC
            $queryoperationitdlc = $this->em
                ->createQuery(
                    "SELECT d, a, t, e
                    FROM AppBundle:OperationITDLC d
                    LEFT JOIN d.availability a
                    LEFT JOIN d.prof t
                    LEFT JOIN d.inge e
                    WHERE
                    d.prof = :d_prof
                    AND d.type= :d_type
                    ORDER BY
                    d.created DESC,
                    d.id DESC"
                )
                ->setParameters(array(
                    'd_prof' => $user->getId(),
                    'd_type' => OperationITDLCType::OPERATION,
                ));
            $operationsitdlc = $queryoperationitdlc->getResult();
        } else {    // Ingénieur
            // Demandes ITDLC
            // La requête provient de celle utilisée pour lister l'ensemble des demandes ITDLC de tous les ingénieurs; /demande-itdlc/list/ingenieur.
            $querydemandeitdlc = $this->em
                ->createQuery(
                    "SELECT u
                    FROM AppBundle:User u
                    WHERE u.nbContribution!=0
                    AND u.nbContribution is not null
                    AND u.id=:iduser
                    ORDER BY u.created DESC, u.id DESC"
                )
                ->setParameter('iduser', $user->getId());
            $demandesitdlc = $querydemandeitdlc->getResult();

            // Opérations ITDLC
            $queryoperationitdlc = $this->em
                ->createQuery(
                    "SELECT d, a, t, e
                    FROM AppBundle:OperationITDLC d
                    LEFT JOIN d.availability a
                    LEFT JOIN d.prof t
                    LEFT JOIN d.inge e
                    WHERE
                    d.inge = :d_inge
                    AND d.type = :d_type
                    ORDER BY
                    d.created DESC,
                    d.id DESC"
                )
                ->setParameters(array(
                    'd_inge' => $user->getId(),
                    'd_type' => OperationITDLCType::OPERATION,
                ));
            $operationsitdlc = $queryoperationitdlc->getResult();
        }

        $form = $this->createForm(UserFormType::class, $user);

        $form->handleRequest($request);
        
        
        if ($form->isSubmitted() && $form->isValid()) {
            $em = $this->getDoctrine()->getManager();
            if (UserType::ENGINEER == $user->getType()) {
                $companyNameOther = $form->get('establishmentNameOther')->getData();
                $company = $em->getRepository(Company::class)->findOneByName($companyNameOther);
                
                if (!$company && $companyNameOther != "") {
                    $company = new Company();
                    $company->setName($companyNameOther);
                    $company->setAvailableForUsers(true);

                    $em->persist($company);
                    $em->flush();

                    $user->setEstablishment($company);
                }
            }
            $this->em->persist($user);
            $this->em->flush();

            $this->addFlash('success', $this->translator->trans('word.type.user.'.$user->getType().'.label', array(), 'word') . ' modifié');

            return $this->redirectToRoute('admin_user_edit', array('user' => $user->getId()));
        }

        return $this->render('Admin/User/add.html.twig', array(
            'form' => $form->createView(),
            'user' => $user,
            'demandespee' => $demandespee,
            'demandesitdlc' => $demandesitdlc,
            'operationsitlc' => $operationsitdlc,
        ));
    }

    /**
     * Active un utilisateur
     *
     * @Route(
     *      "/user/actif",
     *      name = "user_actif"
     * )
     *
     * @param Request $request
     * @return Response
     */
    public function activeAction(Request $request)
    {
        $id = $request->get('id');
        $actif = $request->get('actif');
        $type = $request->get('type');

        $element = $this->em->getRepository(User::class)->find($id);

        if (!$element) {
            throw $this->createNotFoundException(
                'No product found for id '.$id
            );
        }

        if ('is_active' == $type) {
            $element->setIsActive($actif);
        } elseif ('enabled' == $type) {
            if ('false' == $actif) {
                $element->setEnabled(false);
            } else {
                $element->setEnabled($actif);
            }
        } elseif ('isValideInfo' == $type) {
            $element->setIsValideInfo($actif);
        }

        $this->em->flush();

        return new Response();
    }

    /**
     * Supprime un utilisateur (seulement s'il n'a aucune demande PEE, ITDLC ni aucune opération ITDLC ne lui est liée)
     *
     * @Route(
     *      "/users/delete/{user}",
     *      name = "admin_user_delete"
     * )
     *
     * @param User $user
     * 
     * @return Response
     */
    public function deleteAction(User $user)
    {
        $response = new Response();

        $querydemandepee = $this->em->createQuery(
                "SELECT d FROM AppBundle:DemandePEE d WHERE d.cuser = :d_cuser ORDER BY d.created DESC, d.id DESC"
            )->setParameter('d_cuser', $user);
        $demandespee = $querydemandepee->getResult();

        $querydemandeitdlc = $this->em->createQuery(
                "SELECT d FROM AppBundle:OperationITDLC d WHERE d.prof = :d_prof AND d.type = :d_type ORDER BY d.created DESC, d.id DESC"
            )->setParameters(array(
                'd_prof' => $user->getId(),
                'd_type' => OperationITDLCType::DEMANDE,
            ));
        $demandesitdlc = $querydemandeitdlc->getResult();

        if (UserType::TEACHER == $user->getType()) {
            $queryoperationitdlc = $this->em->createQuery(
                    "SELECT d FROM AppBundle:OperationITDLC d WHERE d.prof = :d_prof AND d.type= :d_type ORDER BY d.created DESC, d.id DESC"
                )->setParameters(array(
                    'd_prof' => $user->getId(),
                    'd_type' => OperationITDLCType::OPERATION,
                ));
            $operationsitdlc = $queryoperationitdlc->getResult();
        } else {
            $queryoperationitdlc = $this->em->createQuery(
                    "SELECT d FROM AppBundle:OperationITDLC d WHERE d.inge = :d_inge AND d.type = :d_type ORDER BY d.created DESC, d.id DESC"
                )->setParameters(array(
                    'd_inge' => $user->getId(),
                    'd_type' => OperationITDLCType::OPERATION,
                ));
            $operationsitdlc = $queryoperationitdlc->getResult();
        }

        if (0 == count($demandespee) && 0 == count($demandesitdlc) && 0 == count($operationsitdlc)) {
            $this->em->remove($user);
            $this->em->flush();

            $response->setStatusCode(Response::HTTP_OK);
        } else {
            $response->setStatusCode(Response::HTTP_UNAUTHORIZED);
        }

        return $response;
    }
}
