<?php
/**
 * Created by PhpStorm.
 * User: damien
 * Date: 11/03/2018
 * Time: 10:27
 */

namespace Actigraph\ActipageBaseBundle\Services;


use Actigraph\ActipageBaseBundle\Entity\Inscrit;
use Actigraph\ActipageBaseBundle\Entity\ModuleListe;
use Actigraph\ActipageBaseBundle\Entity\NewsletterGroupes;
use Actigraph\ActipageBaseBundle\Entity\NewsletterParam;
use Actigraph\ActipageModulesReferentiel\FrontModules;
use Doctrine\ORM\EntityManagerInterface;
use Exception;
use Firebase\JWT\ExpiredException;
use Firebase\JWT\JWT;
use PhpParser\Node\Expr\Array_;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Templating\EngineInterface;
use Actigraph\ActipageBaseBundle\Entity\Newsletters;
use Twig\Environment;


class NewsletterService
{
    private $mailer,$templating,$emailFrom,$jwtSecretToken,$doctrine,$requestStack,$dataEncryptionService;

    public function __construct(\Swift_Mailer $mailer,Environment $templating,$params,EntityManagerInterface $doctrine, RequestStack $requestStack, DataEncryptionService $dataEncryptionService)
    {
        $this->mailer= $mailer;
        $this->doctrine = $doctrine;
        $this->requestStack = $requestStack;
        $this->templating = $templating;
        $this->dataEncryptionService = $dataEncryptionService;
        if(isset($params["jwtSecret"]))
            $this->jwtSecretToken = $params["jwtSecret"];
        else
            $this->jwtSecretToken = "TokenToChange12Actigraph"; //Token par défaut si probléme dans configuration
        $this->emailFrom=$params["emailFrom"];
    }

    /**
     * @param Array_ $data (mail, nom, prenom, bdate, groupe, societe, fonction, urlSite, adresse, cp, ville, telFixe, tel, motsCles, commentaire )
     * @param $returnPath
     * @param bool $forceAdd
     * @return bool
     * @throws Exception
     */
    public function addNewInscrit($data,$returnPath,$forceAdd=false){
        if(!isset($data['mail']))
            throw new \Exception("message.error.missingemail");
        if($this->emailAlreadyRegistred($data["mail"]))
            throw new \Exception("message.error.emailalreadyinnewsletter");

        if($forceAdd){
            return $this->saveInscritIntoDb($data);
        }
        //envoi d'un mail de confirmation
        $tokenActivation = JWT::encode(array_merge($data,array("exp"=>(time()+3600))),$this->jwtSecretToken,"HS256");
        $message = (new \Swift_Message("Inscription à la newsletter"))
            ->setFrom($this->emailFrom)
            ->setTo($data["mail"])
            ->setSubject("Inscription à la newsletter")
            ->setBody(
                $this->templating->render(
                    '@ActigraphActipageBaseBundle/Mails/newsletter_confirm_inscription.html.twig',
                    array(
                        "baseUrl"=>$this->requestStack->getCurrentRequest()->getSchemeAndHttpHost(),
                        "confirmLien"=>$this->requestStack->getCurrentRequest()->getSchemeAndHttpHost()."/newsletter/confirm?return=".$returnPath."&token=".$tokenActivation
                    )
                ),
                'text/html'
            );
        $this->mailer->send($message);
        return true;
    }

    public function emailAlreadyRegistred($email){
        if($this->dataEncryptionService->isModuleDataEncryptNeeded(FrontModules::MODULE_NEWSLETTER)){
            $sql = "SELECT mail FROM inscrit";
            $query = $this->doctrine->getConnection()->prepare($sql);
            $query->execute();
            while ($existingInscritEmail = $query->fetch()){
                $existingInscritEmailClear = $this->dataEncryptionService->decryptIfNeeded($existingInscritEmail["mail"],FrontModules::MODULE_NEWSLETTER);
                if($existingInscritEmailClear == $email)
                    return true;
            }
            return false;
        }else{
            $sql = "SELECT mail FROM inscrit WHERE mail = :mail LIMIT 1";
            $query = $this->doctrine->getConnection()->prepare($sql);
            $query->execute(array("mail"=>$email));
            if($query->rowCount() == 0)
                return false;
            return true;
        }

    }


    public function confirmInscription($token){
        try{
            $decoded = JWT::decode($token,$this->jwtSecretToken,array("HS256"));
            if(is_object($decoded)){
                return $this->saveInscritIntoDb((array)$decoded);
            }
        }catch( Exception $e ){
            if ($e instanceof ExpiredException) {
                throw new Exception("message.error.newslettertokenexpire");
            } else {
                throw new Exception("message.error.newslettertokeninvalid");
            }
        }

        return false;
    }

    public function deleteInscrit($data){
        $em = $this->doctrine;

        if(!isset($data['removeMail']))
            throw new \Exception("message.error.missingemail");

        if($this->emailAlreadyRegistred($data["removeMail"]) == false)
            throw new \Exception("message.error.emailnotexistinnewsletter");

        $inscritComplementInfos = [];
        if($this->dataEncryptionService->isModuleDataEncryptNeeded(FrontModules::MODULE_NEWSLETTER)){
            $sql = "SELECT id_inscrit,mail,nom,prenom FROM inscrit";
            $query = $em->getConnection()->prepare($sql);
            $query->execute();
            $idInscritToDelete  = false;
            while ($existingInscritEmail = $query->fetch()){
                $existingInscritEmailClear = $this->dataEncryptionService->decryptIfNeeded($existingInscritEmail["mail"],FrontModules::MODULE_NEWSLETTER);
                if($existingInscritEmailClear == $data["removeMail"]){
                    $idInscritToDelete = $existingInscritEmail["id_inscrit"];

                    $inscritComplementInfos = [
                        "id"=>$idInscritToDelete,
                        "email"=>$data["removeMail"],
                        "nom"=>$this->dataEncryptionService->decryptIfNeeded($existingInscritEmail["nom"],FrontModules::MODULE_NEWSLETTER),
                        "prenom"=>$this->dataEncryptionService->decryptIfNeeded($existingInscritEmail["prenom"],FrontModules::MODULE_NEWSLETTER),
                    ];
                }
            }
        }else{
            /** @var Inscrit $inscrit */
            $inscrit = $em->getRepository('ActigraphActipageBaseBundle:Inscrit')->findOneBy(array("mail"=>$data["removeMail"]));
            $idInscritToDelete = $inscrit->getIdInscrit();

            $inscritComplementInfos = [
                "id"=>$idInscritToDelete,
                "email"=>$data["removeMail"],
                "nom"=>$inscrit->getNom(),
                "prenom"=>$inscrit->getPrenom(),
            ];
        }

        $sqlDeleteInscrit = "DELETE FROM inscrit WHERE id_inscrit=:idInscrit";
        $query = $em->getConnection()->prepare($sqlDeleteInscrit);
        $query->bindParam(":idInscrit", $idInscritToDelete);
        $query->execute();
        try{
            $sqlDeleteStat = 'DELETE FROM newsletter_stats_click WHERE idInscrit=:idInscrit';
            $query = $em->getConnection()->prepare($sqlDeleteStat);
            $query->bindParam(":idInscrit", $idInscritToDelete);
            $query->execute();

            $sqlDeleteGroupe = "DELETE FROM newsletter_groupes_list WHERE inscrit_id=:idInscrit";
            $query = $em->getConnection()->prepare($sqlDeleteGroupe);
            $query->bindParam(":idInscrit", $idInscritToDelete);
            $query->execute();


            $sqlParamNewsletter = "SELECT * FROM newsletter_param LIMIT 1";
            $query = $em->getConnection()->prepare($sqlParamNewsletter);
            $query->execute();
            if($query->rowCount()>0){
                $newsletterParam = $query->fetch();
                if($newsletterParam["email_notification_desinscription"] != ""){
                    $message = (new \Swift_Message())
                        ->setFrom($newsletterParam["from"])
                        ->setTo($newsletterParam["email_notification_desinscription"])
                        ->setSubject("Désinscription à la newsletter de l'utilisateur : ".$inscritComplementInfos["prenom"]." ".$inscritComplementInfos["nom"])
                        ->setBody(
                            $this->templating->render(
                                '@ActigraphActipageBaseBundle/Mails/newsletter_notification_desinscription.html.twig',
                                array(
                                    "baseUrl"=>$this->requestStack->getCurrentRequest()->getSchemeAndHttpHost(),
                                    "inscrit"=>$inscritComplementInfos,
                                )
                            ),
                            'text/html'
                        );
                    $this->mailer->send($message);
                }
            }

        } catch (Exception $exception){
            dump($exception->getMessage());
            //Le client n'a surement pas la newsletter avancée donc ça bloque, pas la peine de gerer l'erreur
        }

        return true;
    }

    private function saveInscritIntoDb($data){

        if($this->emailAlreadyRegistred($data["mail"]))
            return false;


        $inscrit = new Inscrit();

        try{ //Test d'encryptage de l'email pour voir si le service fonctionne bien. Si j'ai une exception alors je stope
            $mail = $this->dataEncryptionService->encyptIfNeeded($data["mail"],FrontModules::MODULE_NEWSLETTER);
            if($mail==false||strlen($mail)==0)
                return false;
        }catch (Exception $e){
            return false;
        }
        $inscrit->setMail($mail);
        $inscrit->setEmailVerif(1);
        $inscrit->setDateinscr(date('d/m/Y'));
        $inscrit->setDatemodif('');
        $inscrit->setErrorid("");

        if(isset($data["nom"]) && $data["nom"] != ""){
            $inscrit->setNom( $this->dataEncryptionService->encyptIfNeeded($data["nom"],FrontModules::MODULE_NEWSLETTER));
        } else {
            $inscrit->setNom("");
        }

        if(isset($data["prenom"]) && $data["prenom"] != ""){
            $inscrit->setPrenom($this->dataEncryptionService->encyptIfNeeded($data["prenom"],FrontModules::MODULE_NEWSLETTER));
        } else {
            $inscrit->setNom("");
        }

        if(isset($data["bdate"]) && $data["bdate"] != ""){
            $inscrit->setBdate($this->dataEncryptionService->encyptIfNeeded($data["bdate"],FrontModules::MODULE_NEWSLETTER));
        } else {
            $inscrit->setBdate("");
        }

        if(isset($data["groupe"]) && $data["groupe"] != ""){
            $inscrit->setGroupe($this->dataEncryptionService->encyptIfNeeded($data["groupe"],FrontModules::MODULE_NEWSLETTER));
        } else {
            $inscrit->setGroupe("");
        }

        if(isset($data["societe"]) && $data["societe"] != ""){
            $inscrit->setSociete($this->dataEncryptionService->encyptIfNeeded($data["societe"],FrontModules::MODULE_NEWSLETTER));
        } else {
            $inscrit->setSociete("");
        }

        if(isset($data["fonction"]) && $data["fonction"] != ""){
            $inscrit->setFonction($this->dataEncryptionService->encyptIfNeeded($data["fonction"],FrontModules::MODULE_NEWSLETTER));
        } else {
            $inscrit->setFonction("");
        }

        if(isset($data["urlSite"]) && $data["urlSite"] != ""){
            $inscrit->setUrlsite($this->dataEncryptionService->encyptIfNeeded($data["urlSite"],FrontModules::MODULE_NEWSLETTER));
        } else {
            $inscrit->setUrlsite("");
        }

        if(isset($data["adresse"]) && $data["adresse"] != ""){
            $inscrit->setAdresse($this->dataEncryptionService->encyptIfNeeded($data["adresse"],FrontModules::MODULE_NEWSLETTER));
        } else {
            $inscrit->setAdresse("");
        }

        if(isset($data["cp"]) && $data["cp"] != ""){
            $inscrit->setCp($this->dataEncryptionService->encyptIfNeeded($data["cp"],FrontModules::MODULE_NEWSLETTER));
        } else {
            $inscrit->setCp("");
        }

        if(isset($data["ville"]) && $data["ville"] != ""){
            $inscrit->setVille($this->dataEncryptionService->encyptIfNeeded($data["ville"],FrontModules::MODULE_NEWSLETTER));
        } else {
            $inscrit->setVille("");
        }

        if(isset($data["telFixe"]) && $data["telFixe"] != ""){
            $inscrit->setTelfixe($this->dataEncryptionService->encyptIfNeeded($data["telFixe"],FrontModules::MODULE_NEWSLETTER));
        } else {
            $inscrit->setTelfixe("");
        }

        if(isset($data["tel"]) && $data["tel"] != ""){
            $inscrit->setTelmobile($this->dataEncryptionService->encyptIfNeeded($data["tel"],FrontModules::MODULE_NEWSLETTER));
        } else {
            $inscrit->setTelmobile("");
        }

        if(isset($data["motsCles"]) && $data["motsCles"] != ""){
            $inscrit->setMotscles($this->dataEncryptionService->encyptIfNeeded($data["motsCles"],FrontModules::MODULE_NEWSLETTER));
        } else {
            $inscrit->setMotscles("");
        }

        if(isset($data["commentaire"]) && $data["commentaire"] != ""){
            $inscrit->setCommentaire($this->dataEncryptionService->encyptIfNeeded($data["commentaire"],FrontModules::MODULE_NEWSLETTER));
        } else {
            $inscrit->setCommentaire("");
        }

        $preuveSecretKey = "ITcGcd24o6Bgax3b6NH0NfhONVIzly4GvPuscESBycc=";
        $userIp = $this->requestStack->getCurrentRequest()->getClientIp();
        $tmp = explode(".",$userIp);
        array_pop($tmp);
        $userIp = implode(".",$tmp).".x";
        $userBrowser = $this->requestStack->getCurrentRequest()->headers->get('User-Agent');
        $timestamp = time();
        $preuveRaw = $userIp."|".$userBrowser."|".$timestamp;
        $encryption_key = base64_decode($preuveSecretKey);
        $iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length('aes-256-cbc'));
        $encrypted = openssl_encrypt($preuveRaw, 'aes-256-cbc', $encryption_key, 0, $iv);
        $encrypted = $encrypted . ':' . base64_encode($iv);
        $rgpd_preuve = "Actipage|".$timestamp."|".$encrypted;

        $inscrit->setRgpdPreuve($rgpd_preuve);

        $em = $this->doctrine;

        if(isset($data["groupes"]) && !empty($data["groupes"])){
            $groupeRepository= $em->getRepository('ActigraphActipageBaseBundle:NewsletterGroupes');

            foreach ($data["groupes"] as $groupeId){
                $object = $groupeRepository->find($groupeId);
                $inscrit->addGroupeObj($object);
            }
        } else {
            $tousInscritGroupe = $em->getRepository('ActigraphActipageBaseBundle:NewsletterGroupes')->findOneBy(array("groupeId"=>1));
            if($tousInscritGroupe != null)
                $inscrit->addGroupeObj($tousInscritGroupe);

        }

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

        //dump("test"); exit;
        return true;
    }

    public function prepareNewsletterHtmlToSend($gabaritHtml,Newsletters $newsletter, $urlTracker, $lienDesinscription, $addTrackers=true){
        $contenu = $newsletter->getNewsletterContenuHtml();

        if($addTrackers){
            $contenu = $this->addTrackingToNewsletterHtml($contenu,$newsletter->getNewsletterId(),$urlTracker,"#IDINSCRIT#");
        }

        $contenu = str_replace('#Desinscription#', "Vous ne souhaitez plus recevoir notre lettre d'information : <a href='".$lienDesinscription."' target='_blank' >Cliquez ici</a>" ,$contenu);
        $contenu = str_replace('#NewsLetterEnLigne#', "Si ce message ne s'affiche pas correctement, <a href='".$this->requestStack->getCurrentRequest()->getSchemeAndHttpHost()."/".$urlTracker."?id=".$newsletter->getNewsletterId()."' target='_blank' >visualisez la version en ligne</a>" ,$contenu);
        $contenu = str_replace('#DateDuJour#', date("d/m/Y") ,$contenu);


        $html = str_replace("#CONTENU#",$contenu,$gabaritHtml);


        //$html = $this->addNewsletterCssInHtml($html);
        return $html;
    }

    private function addTrackingToNewsletterHtml($html,$newsletterId, $urlTracker,$idInscrit){
        $em = $this->doctrine;
        preg_match_all('/href="([^"]*)"/i', $html , $regs);
        preg_match_all("/href='([^\']*)'/i", $html , $regs2);
        $listeLiens = array_merge($regs[1],$regs2[1]);
        if($listeLiens>0){
            foreach ($listeLiens as $lienOriginal){
                /** @var NewsletterUrl $newsletterUrl */
                $newsletterUrl = $em->getRepository("ActigraphActipageBaseBundle:NewsletterUrl")->findOneBy(array("url"=>$lienOriginal,"idnewsletter"=>$newsletterId));
                if ($newsletterUrl != null) {
                    $html = str_replace('href="'.$lienOriginal.'"' , 'href="'.$this->requestStack->getCurrentRequest()->getSchemeAndHttpHost()."/".$urlTracker.'?to='.urlencode($lienOriginal).'&id='.$newsletterId.'&idInscrit=0&idUrl='.$newsletterUrl->getId().'"', $html);
                    $html = str_replace("href='".$lienOriginal."'"  , "href='".$this->requestStack->getCurrentRequest()->getSchemeAndHttpHost()."/".$urlTracker."?to=".urlencode($lienOriginal)."&id=".$newsletterId."&idInscrit=0&idUrl=".$newsletterUrl->getId()."'", $html);
                }
            }
        }

        return $html;
    }

}
