<?php

namespace App\Controller;

use App\Entity\Adherent;
use App\Entity\Comptoir;
use App\Entity\ContactComptoir;
use App\Entity\ContactPrestataire;
use App\Entity\CotisationAdherent;
use App\Entity\CotisationPrestataire;
use App\Entity\EtatPrestataire;
use App\Entity\Geoloc;
use App\Entity\GeolocPrestataire;
use App\Entity\Groupe;
use App\Entity\Import;
use App\Entity\Prestataire;
use App\Entity\Rubrique;
use App\Entity\Siege;
use App\Entity\User;
use App\Entity\Usergroup;
use App\Enum\ImportEnum;
use App\Enum\MoyenEnum;
use App\Events\MLCEvents;
use App\Form\Type\ImportFormType;
use Behat\Transliterator\Transliterator;
use DateTime;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\EntityManagerInterface;
use FOS\UserBundle\Event\UserEvent;
use FOS\UserBundle\Model\UserManagerInterface;
use FOS\UserBundle\Util\TokenGeneratorInterface;
use Sonata\AdminBundle\Controller\CRUDController;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Translation\TranslatorInterface;

class ImportController extends CRUDController
{
    protected $siege;
    protected $header;
    protected $warnings;
    protected $errors;
    protected $nberrors;
    protected $nbsuccess;
    protected $success;
    protected $lineErrors;
    protected $em;
    protected $file;
    protected $security;
    protected $userManager;
    protected $translator;
    protected $tokenGenerator;

    public function __construct(EntityManagerInterface $em, Security $security, UserManagerInterface $userManager, TranslatorInterface $translator, TokenGeneratorInterface $tokenGenerator, EventDispatcherInterface $eventDispatcher)
    {
        $this->header = null;
        $this->warnings = [];
        $this->errors = [];
        $this->nberrors = 0;
        $this->nbsuccess = 0;
        $this->lineErrors = [];
        $this->em = $em;
        $this->security = $security;
        $this->userManager = $userManager;
        $this->translator = $translator;
        $this->tokenGenerator = $tokenGenerator;
        $this->eventDispatcher = $eventDispatcher;
        $this->siege = null;
        $this->sendemail = false;
    }

    public function createAction()
    {
        $this->siege = $this->em->getRepository(Siege::class)->findOneById(1);
        $import = new Import();
        $userLogguedIn = $this->em->merge($this->getUser());
        $import->setUser($userLogguedIn);
        $form = $this->createForm(ImportFormType::class, $import);
        $form->handleRequest($this->getRequest());

        if ($form->isSubmitted() && $form->isValid()) {
            $import = $form->getData();
            $media = $import->getMedia();
            $type = $import->getType();
            $this->sendemail = (bool) $import->getSendemail();

            // Sauvegarder l'import en base de données avant l'essai d'import
            $this->em->persist($import);
            $this->em->flush();
            $idimport = $import->getId();

            $this->importFromCSV($type, $media);

            $import = $this->em->getRepository(Import::class)->findOneById($idimport);
            $import->setEnabled(true);

            $import->setSuccess(json_encode($this->success));
            $import->setWarnings(json_encode($this->warnings));
            $import->setErrors(json_encode($this->errors));
            $import->setNbentityadded($this->nbsuccess);
            $import->setNbentityerror($this->nberrors);
            $this->em->persist($import);
            $this->em->flush();

            if (empty($this->errors)) {
                $this->addFlash(
                    'success',
                    'Import effectué avec succès !'
                );
            } else {
                $this->addFlash(
                    'error',
                    "Il y a eu des erreurs lors de l'import !"
                );
            }

            return $this->redirect($this->admin->generateUrl('show', ['id' => $import->getId()]));
        }

        return $this->renderWithExtraParams('@kohinos/admin/import.html.twig', [
            'action' => 'list',
            'form' => $form->createView(),
            'errors' => $this->errors,
            'warnings' => $this->warnings,
            'success' => $this->success,
            'linkcsverror' => (count($this->lineErrors) > 0) ? $this->generateUrl('getcsv', ['header' => $this->header, 'data' => array_values($this->lineErrors)]) : null,
            'csvparams' => $this->getParameter('app.import.header'),
        ]);
    }

    private function importFromCSV($type, $media)
    {
        // Turning off doctrine default logs queries for saving memory
        $this->em->getConnection()->getConfiguration()->setSQLLogger(null);

        // Get file provider
        $provider = $this->container->get($media->getProviderName());

        $csvRows = $this->parseCSV($provider->getFilesystem()->getAdapter()->getDirectory(), $provider->getReferenceImage($media));
        if (!mb_detect_encoding(implode(';', $csvRows[1]), 'UTF-8', true)) {
            $this->errors['error'] = $this->translator->trans("Le fichier n'est pas encodé en UTF-8 !");

            return [];
        }
        $this->header = implode(';', array_values($csvRows[0]));

        $config = $this->getParameter('app.import.header');

        if (ImportEnum::IMPORT_ADHERENT == $type) {
            $result = $this->importAdherent($csvRows);
        } elseif (ImportEnum::IMPORT_PRESTATAIRE == $type) {
            $result = $this->importPrestataire($csvRows);
        } elseif (ImportEnum::IMPORT_GROUPE == $type) {
            $result = $this->importGroupe($csvRows);
        } elseif (ImportEnum::IMPORT_COMPTOIR == $type) {
            $result = $this->importComptoir($csvRows);
        } else {
            // Ne devrait jamais arriver, mais sait-on jamais !
            $this->errors['error'] = $this->translator->trans('Choisir un type de données à importer !');
        }

        return $result;
    }

    private function slugify($string)
    {
        $string = Transliterator::transliterate($string, '-');

        return Transliterator::urlize($string, '-');
    }

    private function importComptoir($csvRows)
    {
        // Iterate over the reader and write each row to the database
        //groupe;nom;description;adresse;cpostal;ville;latitude;longitude;compte;gestionnaire_email1;gestionnaire_nom1;gestionnaire_prenom1;gestionnaire_phone1;gestionnaire_mobile1;contact1;phone1;email1;contact2;phone2;email2
        $line = 1;
        foreach ($csvRows as $row) {
            if (1 == $line) {
                ++$line;
                continue;
            }
            if (!(array_key_exists('groupe', $row) && array_key_exists('nom', $row))) {
                $this->addError($row, $line, 'nom & groupe', $this->translator->trans("Les colonnes 'nom' et 'groupe' sont obligatoires !"));
                ++$this->nberrors;
                ++$line;
                continue;
            }

            $groupe = array_key_exists('groupe', $row) ? $row['groupe'] : '';
            $nom = array_key_exists('nom', $row) ? $row['nom'] : '';
            if (empty($groupe)) {
                $this->addError($row, $line, 'groupe', $this->translator->trans("Le 'groupe' est obligatoire !"));
                ++$this->nberrors;
                ++$line;
                continue;
            }
            if (empty($nom)) {
                $this->addError($row, $line, 'nom', $this->translator->trans("Le 'nom' est obligatoire !"));
                ++$this->nberrors;
                ++$line;
                continue;
            }
            $description = array_key_exists('description', $row) ? $row['description'] : '';
            $adresse = array_key_exists('adresse', $row) ? $row['adresse'] : '';
            $cpostal = array_key_exists('cpostal', $row) ? $row['cpostal'] : '';
            $ville = array_key_exists('ville', $row) ? $row['ville'] : '';
            $latitude = array_key_exists('latitude', $row) ? $row['latitude'] : '';
            $longitude = array_key_exists('longitude', $row) ? $row['longitude'] : '';
            $compte = array_key_exists('compte', $row) ? $row['compte'] : '';

            $groupeFound = $this->em->getRepository(Groupe::class)->findOneBy(['slug' => $this->slugify($groupe)]);
            if (empty($groupeFound)) {
                $groupeFound = new Groupe();
                $groupeFound->setName($groupe);
                $groupeFound->setSiege($this->siege);
                $this->em->persist($groupeFound);
                $this->addSuccess($row, $line, 'groupe', $this->translator->trans('Groupe ajouté : ') . $groupe);
            }
            $comptoir = $this->em->getRepository(Comptoir::class)->findOneBy(['slug' => $this->slugify($nom), 'groupe' => $groupeFound]);
            if (empty($comptoir)) {
                $comptoir = new Comptoir();
                $comptoir->setGroupe($groupeFound);
                $comptoir->setName($nom);
                if (!empty($description)) {
                    $comptoir->setContent($description);
                } else {
                    $this->addWarning($row, $line, 'description', 'empty');
                }
                if (!empty($compte)) {
                    $comptoir->setCompte($this->tofloat($compte));
                } else {
                    $this->addWarning($row, $line, 'compte', 'empty');
                }
                if (!empty($adresse) || !empty($cpostal) || !empty($ville)) {
                    $geolocFound = new Geoloc();
                    $geolocFound->setAdresse($adresse);
                    $geolocFound->setCpostal(intval($cpostal));
                    $geolocFound->setVille($ville);
                    if (!empty($latitude) && !empty($longitude)) {
                        $geolocFound->setLat((float) $latitude);
                        $geolocFound->setLon((float) $longitude);
                    }
                    $comptoir->setGeoloc($geolocFound);
                }
                // Importer les contacts du comptoir s'ils existent (par défaut en public)
                $cptContact = 1;
                while (array_key_exists('contact' . $cptContact, $row) && $cptContact < 10) {
                    $contact = array_key_exists('contact' . $cptContact, $row) ? $row['contact' . $cptContact] : '';
                    $phone = array_key_exists('phone' . $cptContact, $row) ? $row['phone' . $cptContact] : '';
                    $email = array_key_exists('email' . $cptContact, $row) ? $row['email' . $cptContact] : '';
                    $contactC = new ContactComptoir();
                    $contactC->setComptoir($comptoir);
                    $contactC->setEnabled(true);
                    $contactC->setName($contact);
                    $contactC->setTel($phone);
                    $contactC->setEmail($email);
                    $this->em->persist($contactC);
                    ++$cptContact;
                }

                // Importer les gestionnaires de comptoir s'ils existent
                $groupeGestionnaire = $this->em->getRepository(Usergroup::class)->findOneByName('Comptoir');
                $gestionnaires = $this->importGestionnaires($row, $groupeGestionnaire);
                $comptoir->setGestionnaires($gestionnaires);

                $this->addSuccess($row, $line, 'comptoir', $this->translator->trans('Comptoir ajouté : ') . $nom);
                ++$this->nbsuccess;
                $this->em->persist($comptoir);
                $this->em->flush();
                $this->em->clear();
            } else {
                $this->addError($row, $line, 'nom', $this->translator->trans('Le comptoir avec ce nom {name} existe déjà !', ['name' => $nom]));
                ++$this->nberrors;
            }

            ++$line;
        }
        ksort($this->errors);
        ksort($this->warnings);
    }

    private function importGroupe($csvRows)
    {
        // Iterate over the reader and write each row to the database
        // nom;description;compte;gestionnaire_email1;gestionnaire_nom1;gestionnaire_prenom1;gestionnaire_phone1;gestionnaire_mobile1
        $line = 1;
        foreach ($csvRows as $row) {
            if (1 == $line) {
                ++$line;
                continue;
            }
            $name = array_key_exists('nom', $row) ? $row['nom'] : '';
            if (empty($name)) {
                $this->addError($row, $line, 'nom', $this->translator->trans("Le 'nom' est obligatoire !"));
                ++$this->nberrors;
                ++$line;
                continue;
            }
            $description = array_key_exists('description', $row) ? $row['description'] : '';
            $compte = array_key_exists('compte', $row) ? $row['compte'] : '';
            $groupe = $this->em->getRepository(Groupe::class)->findOneBy(['slug' => $this->slugify($name)]);
            if (empty($groupe)) {
                $groupe = new Groupe();
                $groupe->setSiege($this->em->getRepository(Siege::class)->findOneById(1));
                if (!empty($name)) {
                    $groupe->setName($name);
                } else {
                    $this->addWarning($row, $line, 'name', 'empty');
                }
                if (!empty($content)) {
                    $groupe->setContent($content);
                } else {
                    $this->addWarning($row, $line, 'content', 'empty');
                }
                if (!empty($compte)) {
                    $groupe->setCompte($this->tofloat($compte));
                } else {
                    $this->addWarning($row, $line, 'compte', 'empty');
                }
                // Importer les gestionnaires du groupe s'ils existent
                $groupeGestionnaire = $this->em->getRepository(Usergroup::class)->findOneByName('Gestionnaire de Groupe');
                $gestionnaires = $this->importGestionnaires($row, $groupeGestionnaire);
                $groupe->setGestionnaires($gestionnaires);

                $this->addSuccess($row, $line, 'groupe', $this->translator->trans('Groupe ajouté : ') . $name);
                $this->em->persist($groupe);
                ++$this->nbsuccess;
                $this->em->flush();
                $this->em->clear();
            } else {
                $this->addError($row, $line, 'name', $this->translator->trans("Le groupe avec ce nom '" . $name . "' existe déjà !"));
                ++$this->nberrors;
            }
            ++$line;
        }
        ksort($this->errors);
        ksort($this->warnings);
    }

    private function importPrestataire($csvRows)
    {
        // Iterate over the reader and write each row to the database
        // groupe;adresse;cpostal;ville;raison;metier;statut;responsable;iban;siret;web;horaires;description;rubriques;tags;tauxreconversion;cotisations;gestionnaire_email1;gestionnaire_nom1;gestionnaire_prenom1;gestionnaire_phone1;gestionnaire_mobile1;contact1;phone1;email1;contact2;phone2;email2
        $line = 1;
        foreach ($csvRows as $row) {
            $hasError = false;
            if (1 == $line) {
                ++$line;
                continue;
            }
            if (!array_key_exists('groupe', $row)) {
                $this->addError($row, $line, 'groupe', $this->translator->trans("La colonne 'groupe' est obligatoire !"));
            }
            if (!array_key_exists('adresse', $row)) {
                $this->addError($row, $line, 'adresse', $this->translator->trans("La colonne 'adresse' est obligatoire !"));
            }
            if (!array_key_exists('cpostal', $row)) {
                $this->addError($row, $line, 'cpostal', $this->translator->trans("La colonne 'cpostal' est obligatoire !"));
            }
            if (!array_key_exists('ville', $row)) {
                $this->addError($row, $line, 'ville', $this->translator->trans("La colonne 'ville' est obligatoire !"));
            }
            if (!array_key_exists('raison', $row)) {
                $this->addError($row, $line, 'raison', $this->translator->trans("La colonne 'raison' est obligatoire !"));
            }
            if (!(array_key_exists('groupe', $row) && array_key_exists('adresse', $row) && array_key_exists('cpostal', $row) && array_key_exists('ville', $row) && array_key_exists('raison', $row))) {
                ++$line;
                ++$this->nberrors;
                continue;
            }
            $groupe = array_key_exists('groupe', $row) ? $row['groupe'] : '';
            $adresse = array_key_exists('adresse', $row) ? $row['adresse'] : '';
            $cpostal = array_key_exists('cpostal', $row) ? $row['cpostal'] : '';
            $ville = array_key_exists('ville', $row) ? $row['ville'] : '';
            $raison = array_key_exists('raison', $row) ? $row['raison'] : '';
            if (empty($groupe)) {
                $this->addError($row, $line, 'groupe', $this->translator->trans("Le 'groupe' est obligatoire !"));
            }
            if (empty($adresse)) {
                $this->addError($row, $line, 'adresse', $this->translator->trans("Le 'adresse' est obligatoire !"));
            }
            if (empty($cpostal)) {
                $this->addError($row, $line, 'cpostal', $this->translator->trans("Le 'cpostal' est obligatoire !"));
            }
            if (empty($ville)) {
                $this->addError($row, $line, 'ville', $this->translator->trans("Le 'ville' est obligatoire !"));
            }
            if (empty($raison)) {
                $this->addError($row, $line, 'raison', $this->translator->trans("Le 'raison' est obligatoire !"));
            }
            if (empty($groupe) || empty($adresse) || empty($cpostal) || empty($ville) || empty($raison)) {
                ++$this->nberrors;
                ++$line;
                continue;
            }
            $metier = array_key_exists('metier', $row) ? $row['metier'] : '';
            $statut = array_key_exists('statut', $row) ? $row['statut'] : '';
            $responsable = array_key_exists('responsable', $row) ? $row['responsable'] : '';
            $iban = array_key_exists('iban', $row) ? $row['iban'] : '';
            $siret = array_key_exists('siret', $row) ? $row['siret'] : '';
            $web = array_key_exists('web', $row) ? $row['web'] : '';
            $horaires = array_key_exists('horaires', $row) ? $row['horaires'] : '';
            $description = array_key_exists('description', $row) ? $row['description'] : '';
            $rubriques = array_key_exists('rubriques', $row) ? $row['rubriques'] : '';
            $tags = array_key_exists('tags', $row) ? $row['tags'] : '';
            $tauxreconversion = array_key_exists('tauxreconversion', $row) ? $row['tauxreconversion'] : '';
            $cotisations = array_key_exists('cotisations', $row) ? $row['cotisations'] : '';

            $prestataire = $this->em->getRepository(Prestataire::class)->findOneBy(['slug' => $this->slugify($raison)]);
            if (empty($prestataire)) {
                $prestataire = new Prestataire();

                if (!empty($raison)) {
                    $prestataire->setRaison($raison);
                } else {
                    $this->addWarning($row, $line, 'raison', 'empty');
                }
                if (!empty($metier)) {
                    $prestataire->setMetier($metier);
                } else {
                    $this->addWarning($row, $line, 'metier', 'empty');
                }
                if (!empty($statut)) {
                    $prestataire->setStatut($statut);
                } else {
                    $this->addWarning($row, $line, 'statut', 'empty');
                }
                if (!empty($responsable)) {
                    $prestataire->setResponsable($responsable);
                } else {
                    $this->addWarning($row, $line, 'responsable', 'empty');
                }
                if (!empty($iban)) {
                    $prestataire->setIban($iban);
                } else {
                    $this->addWarning($row, $line, 'iban', 'empty');
                }
                if (!empty($siret)) {
                    $prestataire->setSiret($siret);
                } else {
                    $this->addWarning($row, $line, 'siret', 'empty');
                }
                if (!empty($web)) {
                    $prestataire->setWeb($web);
                } else {
                    $this->addWarning($row, $line, 'web', 'empty');
                }
                if (!empty($horaires)) {
                    $prestataire->setHoraires($horaires);
                } else {
                    $this->addWarning($row, $line, 'horaires', 'empty');
                }
                if (!empty($description)) {
                    $prestataire->setDescription($description);
                } else {
                    $this->addWarning($row, $line, 'description', 'empty');
                }

                $cptContact = 1;
                while (array_key_exists('contact' . $cptContact, $row) && $cptContact < 10) {
                    $contact = array_key_exists('contact' . $cptContact, $row) ? $row['contact' . $cptContact] : '';
                    $phone = array_key_exists('phone' . $cptContact, $row) ? $row['phone' . $cptContact] : '';
                    $email = array_key_exists('email' . $cptContact, $row) ? $row['email' . $cptContact] : '';
                    $contactC = new ContactPrestataire();
                    $contactC->setPrestataire($prestataire);
                    $contactC->setEnabled(true);
                    $contactC->setName($contact);
                    $contactC->setTel($phone);
                    $contactC->setEmail($email);
                    $this->em->persist($contactC);
                    ++$cptContact;
                }
                // Importer les gestionnaires du prestataire s'ils existent
                $groupeGestionnaire = $this->em->getRepository(Usergroup::class)->findOneByName('Prestataire');
                $gestionnaires = $this->importGestionnaires($row, $groupeGestionnaire);
                $prestataire->setUsers($gestionnaires);

                if (!empty($groupe)) {
                    $groupeFound = $this->em->getRepository(Groupe::class)->findOneBy(['slug' => $this->slugify($groupe)]);
                    if (empty($groupeFound)) {
                        $groupeFound = new Groupe();
                        $groupeFound->setName($groupe);
                        $groupeFound->setSiege($this->siege);
                        $this->em->persist($groupeFound);
                        $this->addWarning($row, $line, 'groupe', $this->translator->trans('Groupe introuvable, création du groupe : ') . $groupe);
                    }
                    $prestataire->setGroupe($groupeFound);
                } else {
                    $this->addWarning($row, $line, 'groupe', 'empty');
                }
                if (!empty($cotisations)) {
                    $cotisationArray = explode(',', $cotisations);
                    if (count($cotisationArray) > 0) {
                        foreach ($cotisationArray as $cotisationDetails) {
                            $cotisation = new CotisationPrestataire();
                            $now = new DateTime();
                            $cotisation->setReference('Import du ' . $now->format('d/m/Y H:i'));
                            $userLogguedIn = $this->em->merge($this->getUser());
                            $cotisation->setOperateur($userLogguedIn);
                            $cotisation->setRole('ROLE_SUPER_ADMIN');
                            $cotisation->setExpediteur($prestataire);
                            $cotisation->setMoyen(MoyenEnum::MOYEN_AUTRE);
                            $cotisationDetailsArray = explode(':', $cotisationDetails);
                            if (1 == count($cotisationDetailsArray)) {
                                $cotisation->setMontant(intval($cotisationDetails));
                                $cotisation->getCotisationInfos()->setDebut($now);
                                $cotisation->getCotisationInfos()->setFin(new DateTime('+ 1 year'));
                            } else {
                                $cotisation->setMontant(intval($cotisationDetailsArray[0]));
                                $cotisation->getCotisationInfos()->setAnnee($cotisationDetailsArray[1]);
                                $cotisation->getCotisationInfos()->setDebut(DateTime::createFromFormat('Ymd', intval($cotisationDetailsArray[1]) . '0101'));
                                $cotisation->getCotisationInfos()->setFin(DateTime::createFromFormat('Ymd', intval($cotisationDetailsArray[1]) . '1231'));
                            }
                            $this->em->persist($cotisation);
                            $this->addSuccess($row, $line, 'cotisations', $this->translator->trans('Cotisation ajouté : ') . $groupe);
                        }
                    }
                } else {
                    $this->addWarning($row, $line, 'cotisations', 'empty');
                }
                if (!empty($rubriques)) {
                    $rubriquesArray = explode(',', $rubriques);
                    foreach ($rubriquesArray as $rubrique) {
                        $rubriqueFound = $this->em->getRepository(Rubrique::class)->findOneBy(['slug' => $this->slugify($rubrique)]);
                        if (empty($rubriqueFound)) {
                            $rubriqueFound = new Rubrique();
                            $rubriqueFound->setName($rubrique);
                            $this->em->persist($rubriqueFound);
                            $this->addSuccess($row, $line, 'rubrique', $this->translator->trans('Rubrique ajoutée : ') . $rubrique);
                        }
                        $prestataire->addRubrique($rubriqueFound);
                    }
                } else {
                    $this->addWarning($row, $line, 'rubriques', 'empty');
                }
                if (!empty($tags)) {
                    $tagsArray = explode(',', $tags);
                    foreach ($tagsArray as $tag) {
                        $tagFound = $this->em->getRepository(EtatPrestataire::class)->findOneBy(['slug' => $this->slugify($tag)]);
                        if (empty($tagFound)) {
                            $tagFound = new EtatPrestataire();
                            $tagFound->setName($tag);
                            $this->em->persist($tagFound);
                            $this->addSuccess($row, $line, 'tag', $this->translator->trans('Tag ajouté : ') . $tag);
                        }
                        $prestataire->addEtat($tagFound);
                    }
                } else {
                    $this->addWarning($row, $line, 'tags', 'empty');
                }
                if (!empty($adresse) || !empty($cpostal) || !empty($ville)) {
                    $geolocP = new GeolocPrestataire();
                    $geolocP->setName('Adresse');
                    $geolocP->setPrestataire($prestataire);
                    $geolocFound = new Geoloc();
                    $geolocFound->setEnabled(true);
                    $geolocFound->setAdresse($adresse);
                    $geolocFound->setCpostal(intval($cpostal));
                    $geolocFound->setVille($ville);
                    $geolocP->setGeoloc($geolocFound);
                    $prestataire->setGeolocs([$geolocP]);
                    $this->em->persist($geolocP);
                }
            } else {
                $this->addError($row, $line, 'name', $this->translator->trans("Le prestataire avec cette raison '" . $raison . "' existe déjà !"));
                ++$this->nberrors;
                $hasError = true;
            }
            if (!$hasError) {
                $this->addSuccess($row, $line, 'user', $this->translator->trans('Prestataire bien ajouté : ') . $prestataire->__toString());
                ++$this->nbsuccess;
                $this->em->persist($prestataire);
                $this->em->flush();
                $this->em->clear();
            }

            ++$line;
        }
        ksort($this->errors);
        ksort($this->warnings);
    }

    private function importAdherent($csvRows)
    {
        // Iterate over the reader and write each row to the database
        // groupe;email;prenom;nom;phone;mobile;adresse;cpostal;ville;cotisations
        $line = 1;
        foreach ($csvRows as $row) {
            $hasError = false;
            if (1 == $line) {
                ++$line;
                continue;
            }
            $groupe = array_key_exists('groupe', $row) ? $row['groupe'] : '';
            $firstname = array_key_exists('prenom', $row) ? $row['prenom'] : '';
            $lastname = array_key_exists('nom', $row) ? $row['nom'] : '';
            $email = array_key_exists('email', $row) ? $row['email'] : '';
            $phone = array_key_exists('phone', $row) ? $row['phone'] : '';
            $mobile = array_key_exists('mobile', $row) ? $row['mobile'] : '';
            $adresse = array_key_exists('adresse', $row) ? $row['adresse'] : '';
            $cpostal = array_key_exists('cpostal', $row) ? $row['cpostal'] : '';
            $ville = array_key_exists('ville', $row) ? $row['ville'] : '';
            $cotisations = array_key_exists('cotisations', $row) ? $row['cotisations'] : '';

            if (!(array_key_exists('email', $row))) {
                $this->addError($row, $line, 'email', $this->translator->trans("La colonne 'email' est obligatoire !"));
                ++$line;
                ++$this->nberrors;
                continue;
            }

            $adherent = new Adherent();
            $user = $this->userManager->createUser();
            $user->setConfirmationToken($this->tokenGenerator->generateToken());
            $user->setEnabled(true);
            $user->setPassword(md5(random_bytes(10)));
            $usergroupe = $this->em->getRepository(Usergroup::class)->findOneByName('Adherent');
            $user->addPossiblegroup($usergroupe);
            $user->setGroups([$usergroupe]);
            $user->setAdherent($adherent);
            $adherent->setUser($user);

            if (!empty($firstname)) {
                $user->setFirstname($firstname);
            } else {
                $this->addWarning($row, $line, 'prenom', 'empty');
            }
            if (!empty($lastname)) {
                $user->setLastname($lastname);
            } else {
                $this->addWarning($row, $line, 'nom', 'empty');
            }
            if (!empty($email)) {
                $userFound = $this->em->getRepository(User::class)->findOneBy(['email' => $email]);
                if (!empty($userFound)) {
                    $hasError = true;
                    $this->addError($row, $line, 'email', $this->translator->trans("L'email est déjà utilisé !"));
                    ++$line;
                    ++$this->nberrors;
                    continue;
                } else {
                    $user->setEmail($email);
                    $user->setUsername($email);
                }
            } else {
                $this->addWarning($row, $line, 'email', 'empty');
            }
            if (!empty($phone)) {
                $user->setPhone($phone);
            } else {
                $this->addWarning($row, $line, 'phone', 'empty');
            }
            if (!empty($mobile)) {
                $user->setMobile($mobile);
            } else {
                $this->addWarning($row, $line, 'mobile', 'empty');
            }
            if (!empty($groupe)) {
                $groupeFound = $this->em->getRepository(Groupe::class)->findOneBy(['slug' => $this->slugify($groupe)]);
                if (empty($groupeFound)) {
                    $groupeFound = new Groupe();
                    $groupeFound->setName($groupe);
                    $groupeFound->setSiege($this->siege);
                    $this->em->persist($groupeFound);
                    $this->addSuccess($row, $line, 'groupe', $this->translator->trans('Groupe ajouté : ') . $groupe);
                }
                $adherent->setGroupe($groupeFound);
            } else {
                $this->addWarning($row, $line, 'groupe', 'empty');
            }
            if (!empty($cotisations)) {
                $cotisationArray = explode(',', $cotisations);
                if (count($cotisationArray) > 0) {
                    foreach ($cotisationArray as $cotisationDetails) {
                        $cotisation = new CotisationAdherent();
                        $now = new DateTime();
                        $cotisation->setReference('Import du ' . $now->format('d/m/Y H:i'));
                        $userLogguedIn = $this->em->merge($this->getUser());
                        $cotisation->setOperateur($userLogguedIn);
                        $cotisation->setRole('ROLE_ADHERENT');
                        $cotisation->setExpediteur($adherent);
                        $cotisation->setMoyen(MoyenEnum::MOYEN_AUTRE);
                        $cotisationDetailsArray = explode(':', $cotisationDetails);
                        if (1 == count($cotisationDetailsArray)) {
                            $cotisation->setMontant(intval($cotisationDetails));
                            $cotisation->getCotisationInfos()->setDebut($now);
                            $cotisation->getCotisationInfos()->setFin(new DateTime('+ 1 year'));
                        } else {
                            $cotisation->setMontant(intval($cotisationDetailsArray[0]));
                            $cotisation->getCotisationInfos()->setAnnee($cotisationDetailsArray[1]);
                            $cotisation->getCotisationInfos()->setDebut(DateTime::createFromFormat('Ymd', intval($cotisationDetailsArray[1]) . '0101'));
                            $cotisation->getCotisationInfos()->setFin(DateTime::createFromFormat('Ymd', intval($cotisationDetailsArray[1]) . '1231'));
                        }
                        $this->em->persist($cotisation);
                        $this->addSuccess($row, $line, 'cotisations', $this->translator->trans('Cotisation ajouté : ') . $groupe);
                    }
                }
            } else {
                $this->addWarning($row, $line, 'cotisations', 'empty');
            }
            if (!empty($adresse) || !empty($cpostal) || !empty($ville)) {
                $geolocFound = new Geoloc();
                $geolocFound->setAdresse($adresse);
                $geolocFound->setCpostal(intval($cpostal));
                $geolocFound->setVille($ville);
                $adherent->setGeoloc($geolocFound);
            }
            if (!$hasError) {
                $this->addSuccess($row, $line, 'user', $this->translator->trans('Utilisateur bien ajouté : ') . $user->__toString());
                ++$this->nbsuccess;
                $user->setPasswordRequestedAt(new \DateTime());
                $this->userManager->updateUser($user);
                if ($this->sendemail) {
                    $this->eventDispatcher->dispatch(MLCEvents::REGISTRATION_ADHERENT, new UserEvent($user, $this->getRequest()));
                }
                $this->em->flush();
                $this->em->clear();
            }

            ++$line;
        }
        ksort($this->errors);
        ksort($this->warnings);
    }

    /**
     * Open and parse .CSV file.
     *
     * @param string $filePath        Path of the file
     * @param string $fileName        Name of the file
     * @param bool   $ignoreFirstLine If true, ignore first line
     *
     * @return array Array of parsed values with array's key = firstline
     */
    private function parseCSV($filePath, $fileName, $ignoreFirstLine = false)
    {
        $csv = new \SplFileObject($filePath . '/' . $fileName);

        $rows = [];
        $firstline = null;
        if (($handle = fopen($csv->getRealPath(), 'r')) !== false) {
            $i = 0;
            while (($data = fgetcsv($handle, null, ';')) !== false) {
                ++$i;
                if (1 == $i) {
                    $firstline = $data;
                    $rows[] = $data;
                    if ($ignoreFirstLine) {
                        continue;
                    }
                } else {
                    if (count($firstline) != count($data)) {
                        $this->addError($data, $i, 'Ligne entière', $this->translator->trans("La ligne ne contient pas le bon nombre d'éléments requis !"));
                        ++$this->nberrors;
                        continue;
                    }
                    $rows[] = array_combine(array_values($firstline), array_values($data));
                }
            }
            fclose($handle);
        }

        return $rows;
    }

    /**
     * Import manager of comptoir / groupe / presta.
     *
     * @param array     $row    Value of line imported
     * @param Usergroup $groupe Groupe add to manager imported
     *
     * @return User Manager created
     */
    private function importGestionnaires($row, Usergroup $groupe)
    {
        $cptGestionnaire = 1;
        $users = new ArrayCollection();
        while (array_key_exists('gestionnaire_email' . $cptGestionnaire, $row) && !empty($row['gestionnaire_email' . $cptGestionnaire]) && $cptGestionnaire < 10) {
            $email = array_key_exists('gestionnaire_email' . $cptGestionnaire, $row) ? $row['gestionnaire_email' . $cptGestionnaire] : '';

            $userFound = $this->em->getRepository(User::class)->findOneBy(['email' => $email]);
            if (!empty($userFound)) {
                $userFound->addPossiblegroup($groupe);
                $users[] = $userFound;
                $this->em->persist($userFound);
            } else {
                $nom = array_key_exists('gestionnaire_nom' . $cptGestionnaire, $row) ? $row['gestionnaire_nom' . $cptGestionnaire] : '';
                $prenom = array_key_exists('gestionnaire_prenom' . $cptGestionnaire, $row) ? $row['gestionnaire_prenom' . $cptGestionnaire] : '';
                $phone = array_key_exists('gestionnaire_phone' . $cptGestionnaire, $row) ? $row['gestionnaire_phone' . $cptGestionnaire] : '';
                $mobile = array_key_exists('gestionnaire_mobile' . $cptGestionnaire, $row) ? $row['gestionnaire_mobile' . $cptGestionnaire] : '';

                $adherent = new Adherent();
                $user = $this->userManager->createUser();
                $user->setConfirmationToken($this->tokenGenerator->generateToken());
                $user->setEnabled(true);
                $user->setPassword(md5(random_bytes(10)));
                $usergroupe = $this->em->getRepository(Usergroup::class)->findOneByName('Adherent');
                $user->addPossiblegroup($usergroupe);
                $user->addPossiblegroup($groupe);
                $user->setGroups([$groupe]);
                $user->setFirstname($prenom);
                $user->setLastname($nom);
                $user->setPhone($phone);
                $user->setMobile($mobile);
                $user->setEmail($email);
                $user->setUsername($email);
                $user->setAdherent($adherent);
                $adherent->setUser($user);
                $users[] = $user;
                $this->em->persist($user);
                $this->em->persist($adherent);
                $this->em->flush();
            }
            if ($this->sendemail) {
                $this->eventDispatcher->dispatch(MLCEvents::REGISTRATION_ADHERENT, new UserEvent($user, $this->getRequest()));
            }
            ++$cptGestionnaire;
        }

        return $users;
    }

    private function addSuccess($row, $line, $key, $message = '')
    {
        $csvline = implode(';', array_values($row));
        $this->success[$line][$key] = $message;
    }

    private function addError($row, $line, $key, $err = '')
    {
        $this->lineErrors[$line] = implode(';', array_values($row));
        $this->errors[$line][$key] = (array_key_exists($key, $row) ? (!empty($row[$key]) ? '"' . $row[$key] . '"' : '') : '') . ' [' . $err . ']';
    }

    private function addWarning($row, $line, $key, $err = '')
    {
        $csvline = implode(';', array_values($row));
        if ('empty' == $err) {
            $errString = $this->translator->trans('Valeur vide !');
            $this->warnings[$line][$key] = '[' . $errString . ' ]';
        } elseif ('invalid' == $err) {
            $errString = $this->translator->trans('Valeur invalide !');
            $this->warnings[$line][$key] = '"' . (array_key_exists($key, $row) ? $row[$key] : '') . '" [' . $errString . ']';
        } elseif ('' != $err) {
            $this->warnings[$line][$key] = '"' . (array_key_exists($key, $row) ? $row[$key] : '') . '" [' . $err . ']';
        }
    }

    private function tofloat($num)
    {
        $dotPos = strrpos($num, '.');
        $commaPos = strrpos($num, ',');
        $sep = (($dotPos > $commaPos) && $dotPos) ? $dotPos :
            ((($commaPos > $dotPos) && $commaPos) ? $commaPos : false);

        if (!$sep) {
            return floatval(preg_replace('/[^0-9]/', '', $num));
        }

        return floatval(
            preg_replace('/[^0-9]/', '', substr($num, 0, $sep)) . '.' .
            preg_replace('/[^0-9]/', '', substr($num, $sep + 1, strlen($num)))
        );
    }
}
