<?php

namespace AppBundle\Export;

use AppBundle\Entity\DemandePEE;
use AppBundle\Entity\OperationITDLC;
use AppBundle\Entity\User;
use AppBundle\Enum\DemandePEEState;
use AppBundle\Enum\OperationITDLCType;
use AppBundle\Enum\UserHonorific;
use AppBundle\Enum\UserJobTeacherCategory;
use AppBundle\Enum\UserJobTeacher;
use AppBundle\Enum\UserJobEngineerCategory;
use AppBundle\Enum\UserJobEngineer;
use AppBundle\Enum\UserRep;
use AppBundle\Enum\UserType;
use Symfony\Component\HttpFoundation\StreamedResponse;

/**
 *
 * @author Bastien Gatellier <contact@bgatellier.fr>
 */
class UserExporter extends AbstractExcelExporter
{
    /**
     *
     * @param  User[]   $users
     * @param  string $filename
     * @return StreamedResponse
     * @throws \PhpOffice\PhpSpreadsheet\Exception
     * @throws \PhpOffice\PhpSpreadsheet\Writer\Exception
     */
    public function export(array $users, string $filename): StreamedResponse
    {
        ini_set("max_execution_time", 60000);
        ini_set("memory_limit", "256M");
        ignore_user_abort(1);

        $isTeacher = UserType::TEACHER === $users[0]->getType();
        $rows = [];

        $wordYes = $this->trans('word.yes', [], 'word');
        $wordNo = $this->trans('word.no', [], 'word');

        $headers = array(
            $this->trans('form.username.label', [], 'form'),
            $this->trans('form.email.label', [], 'form'),
            $this->trans('form.honorific.label', [], 'form'),
            $this->trans('form.firstname.label', [], 'form'),
            $this->trans('form.lastname.label', [], 'form'),
            'Téléphone',
            'Portable',
            'Domaine de formation',
            'Niveau de formation',
            'Classe(s)',
            'Domaine',
            'Métier',
            $isTeacher ? 'Nom établissement' : 'Nom entreprise',
            'Partenaire',
            $this->trans('form.address.label', [], 'form'),
            'Code postal',
            $this->trans('form.city.label', [], 'form'),
            $this->trans('form.notes.label', [], 'form'),
            $this->trans('form.date.registration.label', [], 'form'),
            'Compte actif',
            'Utilisateur actif',
            'Utilisateur disponible (ITDLC)',
            $this->trans('form.newsletter.label', [], 'form'),
            'Nb Opérations ITDLC',
            'Nb Demandes ITDLC',
        );
        if ($isTeacher) {
            $headers[] = 'Nb Opérations PEE';
            $headers[] = 'Nb Demandes PEE';
            $headers[] = $this->trans('form.academy.label', [], 'form');
            $headers[] = $this->trans('form.rep.label', [], 'form');
        }
        else {
            // $headers[] = 'Détail fonction professionnelle';
            // $headers[] = 'Détail de la formation'; 
            $headers[] = 'Parlez-nous de vous';
        }

        foreach ($users as $user) {

           
            $demandepee = '';

            // TODO: include the related entities into the query that leads to the $users array, in order to avoid additional requests
            if ($isTeacher) {
                /* Nb Opération itdlc */

//                $queryopeitdlc = $this->em
//                    ->createQuery("SELECT o FROM AppBundle:OperationITDLC o WHERE o.type=:type AND o.prof=:user")
//                    ->setParameters(array(
//                        'type' => OperationITDLCType::OPERATION,
//                        'user' => $user,
//                    ));
//                $opeitdlc = count($queryopeitdlc->getResult());
                $opeitdlc = $this->countOperationsItdlc($user, OperationITDLCType::OPERATION);

                /* Nb Demande itdlc */
//                $querydemandeitdlc = $this->em
//                    ->createQuery("SELECT o FROM AppBundle:OperationITDLC o WHERE o.type=:type AND o.prof=:user")
//                    ->setParameters(array(
//                        'type' => OperationITDLCType::DEMANDE,
//                        'user' => $user,
//                    ));
//                $demandeitdlc = count($querydemandeitdlc->getResult());
                $demandeitdlc = $this->countOperationsItdlc($user, OperationITDLCType::DEMANDE);

                /* Nb Opération pee */
//                $queryopepee = $this->em
//                    ->createQuery("SELECT o FROM AppBundle:DemandePEE o WHERE o.state=:state AND o.cuser=:user")
//                    ->setParameters(array(
//                        'state' => DemandePEEState::REGISTERED,
//                        'user' => $user,
//                    ));
//                $opeipee = count($queryopepee->getResult());
                $opeipee = $this->countApplicationsPee($user, DemandePEEState::REGISTERED);

                /* Nb Demande pee */
//                $querydemandepee = $this->em
//                    ->createQuery("SELECT o FROM AppBundle:DemandePEE o WHERE o.cuser=:user")
//                    ->setParameter('user', $user);
//                $demandepee = count($querydemandepee->getResult());
                $demandepee = $this->countApplicationsPee($user);

                $jobClass = UserJobTeacher::class;
                $jobCategoryClass = UserJobTeacherCategory::class;
            } else {
                /* Nb Opération itdlc */
//                $queryopeitdlc = $this->em
//                    ->createQuery("SELECT o FROM AppBundle:OperationITDLC o WHERE o.type=:type AND o.inge=:user")
//                    ->setParameters(array(
//                        'type' => OperationITDLCType::OPERATION,
//                        'user' => $user,
//                    ));
//                $opeitdlc = count($queryopeitdlc->getResult());
                $opeitdlc = $this->countOperationsItdlc($user, OperationITDLCType::OPERATION);

                /* Nb Demande itdlc */
                $demandeitdlc = $user->getNbContribution();

                $jobClass = UserJobEngineer::class;
                $jobCategoryClass = UserJobEngineerCategory::class;
            }

            $userHonorifics = $this->constTranslator->trans(UserHonorific::class, $user->getHonorific());
            $userJobCategory = $this->constTranslator->trans($jobCategoryClass, $user->getCategoryJob());
            
            $userJob = ($user->getJob() == "" || $user->getJob() == "other") ? $user->getJobOther() : array_shift($this->constTranslator->trans($jobClass, $user->getJob()));
           
            $userEstablishmentName = '';
            if ($isTeacher) {
                $userEstablishmentName = $user->getEstablishmentName();
            } else if ($establishment = $user->getEstablishment()) {
                $userEstablishmentName = $establishment->getName();
            }

            $row = array(
                $user->getUsername(),
                $user->getEmail(),
                array_shift($userHonorifics),
                $user->getFirstname(),
                $user->getLastname(),
                $user->getPhone(),
                $user->getMobile(),
                $user->getFormationType(),
                $user->getFormation(),
                implode(',', $user->getClassroom()),
                array_shift($userJobCategory),
                $userJob,
                $userEstablishmentName,
                $user->getEstablishment() > 0 ? $user->getEstablishment()->getPartnerGroup() : "",
                $user->getEstablishmentAddress(),
                $user->getEstablishmentZipcode(),
                $user->getEstablishmentCity(),
                $user->getNote(),
                $user->getCreated() instanceof \DateTime ? $user->getCreated()->format('d/m/Y') : '',
                $user->isEnabled() ? $wordYes : $wordNo,
                $user->getIsActive() ? $wordYes : $wordNo,
                $user->getIsAvailable() ? $wordYes : $wordNo,
                $user->getNewsletter() ? $wordYes : $wordNo,
                $opeitdlc,
                $demandeitdlc,
            );

            if ($isTeacher) {
                $userRepLevel = $this->constTranslator->trans(UserRep::class, $user->getRep());

                $row[] = $opeipee;
                $row[] = $demandepee;
                $row[] = $user->getAcademy();
                $row[] = array_shift($userRepLevel);
            }
            else {
                // $row[] = $user->getDetailFunction();
                // $row[] = $user->getDetailFormation();  
                $row[] = $user->getAboutMe();
            }

            $rows[] = $row;
        }

        $this->createSpreadsheet($headers, $rows, $filename);

        $this->saveTo('uploads/export/');

        return $this->createStreamedResponse();
    }

    /**
     * Get the number of applications in the given state, for a given user.
     * @param User        $user
     * @param string|null $state
     * @return int
     */
    private function countApplicationsPee(User $user, string $state = null)
    {
        $applications = $user->getDemandepee();

        if ($state) {
            $applications = $applications->filter(function(DemandePEE $application) use ($state) {
                return $state === $application->getState();
            });
        }

        return count($applications);
    }

    /**
     * Count the number of ITDLC operations or applications where the user is a teacher
     * @param User   $user
     * @param string $operationType
     * @return int
     */
    private function countOperationsItdlc(User $user, string $operationType): int
    {
        $userOperations = UserType::TEACHER === $user->getType() ? $user->getProfitdlc() : $user->getIngeitdlc();

        $userOperations = $userOperations->filter(function(OperationITDLC $operation) use ($operationType) {
            return $operationType === $operation->getType();
        });

        return count($userOperations);
    }
}
