<?php
namespace Modules\Connexion\Controller;

use Entity\Model\Hastutil;
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
use GuzzleHttp\Psr7\Response;
use Helpers\Outil\Mail;
use Helpers\Outil\Outils;
use Modules\Index\Outil\OutilDoubleAuthentification;
use Skeleton\Controller\Controller;

class DoubleAuthentificationController extends Controller
{
    /**
     * @var array<mixed> $doubleAuthentificationActive
     */
    protected $doubleAuthentificationActive;

    /**
     * @var array<mixed> $post
     */
    protected $post;

    /**
     * @return Response|void
     */
    public function init()
    {
        // on vérifie que la double authentification est active, et que le code d'authentification n'a pas déjà été renseigné par l'utilisateur
        $this->post = $this->request->getParsedBody(true);
        if (!(count($this->post) && isset($this->post['codeAuth']))
            && !(isset($_COOKIE[\strtoupper($this->post['ID']) . '_DbleAuthValide']))
            && ($_COOKIE[\strtoupper($this->post['ID']) . '_DbleAuthValide']??null) != true
        ) {
            $doubleAuthentificationActive = OutilDoubleAuthentification::doubleAuthActive($this->pdo);
            if (!($doubleAuthentificationActive['dbleAuthActive'] && isset($this->post['postActif']) && $this->post['postActif'] == 1)) {
                return $this->redirect('Connexion.Connexion.connexion');
            }
        }
    }

    /**
     * @return Response|string|void
     */
    public function doubleAuthAction()
    {
        $trad = $this->getTranslationService();

        $postSoumissionForm = $this->request->getParsedBody(true);
        $_SESSION['Session_Langue'] = $postSoumissionForm['langue'] ?? '';
        $dbleAuthFrequence = (OutilDoubleAuthentification::doubleAuthActive($this->pdo))['dbleAuthFrequence'];
        // si le code d'authentification a été renseigné on vérifie qu'il est bon et renvoie vers la connexion
        if (count($postSoumissionForm) && isset($postSoumissionForm['codeAuth'])) {
            if (empty($postSoumissionForm['codeAuth'])) {
                $return['MsgErreur'] = 'Code vide';
                $messageErreur = $trad->t('Veuillez renseigner le code qui vous a été envoyé par email.');
            }
            // tester si le code est bon
            try {
                $verify = (array)JWT::decode(trim($postSoumissionForm['token']), new Key($postSoumissionForm['codeAuth'], 'HS256'));
            } catch (\Exception $e) {
                $return['MsgErreur'] = $e->getMessage();
            }

            if (isset($return['MsgErreur']) && $return['MsgErreur'] != '') {
                switch ($return['MsgErreur']) {
                    case 'Signature verification failed':
                        $messageErreur = $trad->t('Code d\'authentification invalide');
                        break;
                    case 'Expired token':
                        $messageErreur = $trad->t('Code expiré');
                        break;
                }
                return new Response(200, [], $this->renderer->render('@popup-erreur/erreurAlerteEtAvertissement', [
                    'params' => [
                        'alerte'    => $messageErreur ?? ''
                    ]
                ]));
            } elseif (isset($verify['content'])) {
                $verify['content'] = (array)$verify['content'];

                if (!empty($verify['content'])) {
                    $verify['content']['dbleAuthOk'] = true;

                    $arrCookieOptions = [];
                    $valeurCookie = [];

                    if (Outils::isHttps()) {
                        $arrCookieOptions['secure'] = true;
                    }

                    $arrCookieOptions['samesite'] = 'Lax';
                    $arrCookieOptions['httponly'] = true;
                    $arrCookieOptions['path'] = $this->contenaire->get('baseForCookie');

                    switch ($dbleAuthFrequence) {
                        case '':
                            $arrCookieOptions['expires'] = time() + 60;
                            break;
                        case 'H':
                            $arrCookieOptions['expires'] = time() + 60 * 60 * 24 * 7;
                            break;
                        case 'M':
                            $arrCookieOptions['expires'] = time() + 60 * 60 * 24 * 30;
                            break;
                        case 'T':
                            $arrCookieOptions['expires'] = time() + 60 * 60 * 24 * 30 * 3;
                            break;
                        case 'S':
                            $arrCookieOptions['expires'] = time() + 60 * 60 * 24 * 30 * 6;
                            break;
                        case 'A':
                            $arrCookieOptions['expires'] = time() + 60 * 60 * 24 * 365;
                            break;
                    }
                    $valeurCookie = [
                        'dbleAuthValide'    => true,
                        'dbleAuthFrequence' => $dbleAuthFrequence,
                        'exp'               => $arrCookieOptions['expires'] ?? (time() + 60)
                    ];
                    $valeurCookie = JWT::encode($valeurCookie, $this->JWTKEY, 'HS256');
                    \setcookie(\strtoupper($verify['content']['user']) . '_DbleAuthValide', $valeurCookie, $arrCookieOptions);
                    // OutilDoubleAuthentification::updateEmpreinteNumerique($this->pdo, $user, $verify['content']['empreinteNumerique']);
                    return new Response(301, [], (string) \json_encode([
                        'statut' => 'O',
                        'path' => $this->router->generateUri('Connexion.Connexion.connexion'),
                        'post' => (array)$verify['content'],
                    ]));
                } else {
                    return new Response(200, [], $this->renderer->render('@popup-erreur/erreurAlerteEtAvertissement', [
                        'params' => [
                            'alerte'        => $this->getTranslationService()->t('Le code saisi n\'est pas valide.'),
                            'titrePopup'    => $this->getTranslationService()->t('Code invalide'),
                        ]
                    ]));
                }
            }
        } else { // sinon on génère un nouveau code d'authentification, qui servira de clé pour décoder le JWT contenant les infos de connexion
            $user = (new Hastutil($this->pdo))->find(\strtoupper($this->post['user']));

            $tokenAuthentification = [];
            $codeAuthentification  = \rand(111111, 999999);
            
            $tokenAuthentification['content'] = $this->post;
            $tokenAuthentification['exp'] = time()+60*6;
            $tokenAuthentification = JWT::encode($tokenAuthentification, (string)$codeAuthentification, 'HS256');
            Mail::generateMail(
                $this->pdo,
                $this->getTranslationService(),
                $user['EMAIL'],
                'INT_DBLE_AUTH',
                $user['COD_LNG'],
                [
                    'NOM_UTILISATEUR' => $user['NOM'],
                    'TOKEN' => $codeAuthentification,
                ]
            );
            
            return $this->renderer->render('@connexion/doubleAuth/connexionCode', [
                'token'         => $tokenAuthentification,
                'ContexteMobile'=> $_SESSION['ContexteMobile']??null,
                'MobilityLogin' => $_SESSION['MobilityLogin']??null,
                'application'   => $this->post['application']
            ]);
        }
    }
}
