<?php

namespace Modules\Evaluation\Controller;

use Entity\Model\CampEnt;
use Entity\Model\CampEve;
use Entity\Model\CampQstQ;
use Entity\Model\CampRepQst;
use Entity\Model\Fourniss;
use Firebase\JWT\Key;
use GuzzleHttp\Psr7\Response;
use Helpers\Ariane\Ariane;
use Helpers\Session\Session;
use Helpers\User\User;
use Modules\Evaluation\Repository\Evaluation;
use Skeleton\Controller\Controller;
use Helpers\Pagination\PaginatorGestion;
use Modules\Evaluation\Service\EvaluationService;
use Helpers\Session\Enums\MenuTopEnum;

class EvaluationController extends Controller
{


    /**
     *
     * @var bool
     */
    private bool $typeConnexionExterne = false;

    /**
     *
     * @var array<mixed>
     */
    private array $jwtPayload = [];

    private EvaluationService $evaluationService;

    private Evaluation $evaluationRepository;

    /**
     *
     * Gestion des droit et gestion du JWT
     *
     * init
     *
     * @return void|Response|string
     */
    public function init()
    {
        $jwt = $this->request->getAttribute('jwt');

        $this->evaluationService    = new EvaluationService($this->pdo, $this->getTranslationService());
        $this->evaluationRepository = new Evaluation($this->pdo);

        if ($jwt && $jwt != 'NULL') {
            try {
                $verify           = \Firebase\JWT\JWT::decode($jwt, new Key($this->JWTKEY, 'HS256'));
                $this->jwtPayload = (array) $verify;
                // Initialisation des variables de session
                $_SESSION['UserExterne']   = $this->typeConnexionExterne = true;
                $_SESSION['Session_Login'] = trim($this->jwtPayload['ID_NOTEUR']);
                $_SESSION['email']         = $this->jwtPayload['EMAIL_NOTEUR'];
            } catch (\Exception $e) {
                return $this->redirect($this->contenaire->get('base') . 'index.php');
            }
        }

        if (isset($_SESSION['UserExterne']) || $this->request->getAttribute('externe') == 1) {
            $this->typeConnexionExterne = true;
        }
    }

    /**
     * @param array<mixed> $post
     */
    public function indexAction($post = [], bool $visu = false): string
    {
        if (!Session::verifySessionTypeMenuTop(MenuTopEnum::RelationFournisseurs)) {
            Session::setSessionTypeMenuTop(MenuTopEnum::RelationFournisseurs);
        }
        $post = count($post) ? $post : $this->request->getParsedBody();

        /* trad */

        $trad = $this->getTranslationService();

        $paginator = new PaginatorGestion();
        $paginator->generate(0, 'crq.ID_CAMP');

        $listeNotationEnCours = $this->evaluationRepository->getNotation($post, $visu);

        if ($this->typeConnexionExterne) {
            $layout = 'layout-externe.twig';
        } else {
            $layout = 'layout.twig';
            Ariane::generate(0, $trad->t('Gestion'), $post, PaginatorGestion::getNbrArticle());
        }

        $infoPagination = PaginatorGestion::getInfoPagination();

        return $this->renderer->render('@Evaluation/Evaluation/gestionEvaluation', [
            'listeNotationEnCours' => $listeNotationEnCours,
            'infoPagination' => $infoPagination,
            'post' => $post,
            'menuActive' => 'Evaluations',
            'userExterne' => $this->typeConnexionExterne,
            'layout' => $layout,
            'visu' => $visu
        ]);
    }

    /**
     * indexVisuAction
     *
     * @return string
     */
    public function indexVisuAction()
    {

        $visu = $this->request->getAttribute('visu');
        $post = $this->request->getParsedBody();
        return $this->indexAction($post, $visu ? true : false);
    }

    /**
     * detailCampagneFounisseurByUserAction
     *
     * @return string
     */
    public function detailCampagneFounisseurByUserAction()
    {
        $post   = $this->request->getParsedBody();
        $idcamp = $this->request->getAttribute('idCamp');
        $visu   = $this->request->getAttribute('visu');

        $paginator = new PaginatorGestion();
        $paginator->generate(0, 'crq.ID_CAMP');

        $listeNotationEnCours = $this->evaluationRepository->getDetailEvaluationEnCoursParFournisseur($_SESSION['Session_Login'], $post, $idcamp, $visu);

        $infoPagination = PaginatorGestion::getInfoPagination();

        return $this->renderer->render('@Evaluation/Evaluation/gestionEvaluationDetail', [
            'listeNotationEnCours' => $listeNotationEnCours,
            'infoPagination' => $infoPagination,
            'post' => $post,

            'menuActive' => Session::verifySessionTypeMenuTop(MenuTopEnum::S2C) ? 'Consultations' : 'Evaluations',
            'menuLeft' => 'ratings',
            'idcamp' => $idcamp,
            'visu' => $visu

        ]);
    }


    /**
     * saisieDeReponseAction
     *
     * @param  array<mixed> $post
     * @param  string $idcamp
     * @param  string $idFrs
     * @param  bool $visu
     * @return string
     */
    public function saisieDeReponseAction(array $post = [], string $idcamp = '', string $idFrs = '', bool $visu = false)
    {

        $post       = count($post) ? $post : $this->request->getParsedBody();
        $idcamp     = $idcamp ? $idcamp : $this->request->getAttribute('idCamp');
        $idFrs      = $idFrs ? $idFrs : $this->request->getAttribute('idFrs');
        $user       = $this->request->getAttribute('user');
        $externeUrl = $this->request->getAttribute('externe');
        $canEdit    = $visu ? false : ($user ? false : true);
        // $canEdit = $externeUrl == 'camapgnePrevu' ? false : true;
        /* trad */

        $trad = $this->getTranslationService();

        // si on vient de saisieVisu et qu'on veut visualiser les réponses données par un autre évaluateur
        if (isset($post['user_visu']) && $post['user_visu'] != '') {
            $user = $post['user_visu'];
        }

        // est-ce que le noteur est le dépouilleur de la campagne ?
        $campaignCreator = (new CampEnt($this->pdo))->find(['ID_CAMP' => $idcamp])['CREEEPAR'];
        $isDepouilleur   = ($campaignCreator == $_SESSION['Session_Login']) && !$visu;

        $externeForm = $this->request->getAttribute('externe') ?? $this->typeConnexionExterne == true ? 1 : -1;

        $listeThemeCampTmp = $listeQuestion = $listeQuestionPropose = [];

        $this->evaluationService->controleThemeEtQuestionPourSaisie(
            $listeThemeCampTmp,
            $listeQuestion,
            $listeQuestionPropose,
            $idFrs,
            $idcamp,
            $externeForm,
            $canEdit,
            $user
        );


        $rater = $user ? $user : $_SESSION['Session_Login'];

        $commentaireGlobal = (new CampRepQst($this->pdo))->find([
            'ID_CAMP' => $idcamp,
            'CODE_FOU' => $idFrs,
            'ID_THEME' => '',
            'ID_QUEST' => 0,
            'COD_NOTEUR' => $rater
        ], ['COMMENTAIRE'])['COMMENTAIRE'];

        $camp     = new CampEnt($this->pdo);
        $infoCamp = $camp->find(['ID_CAMP' => $idcamp], ['LIBELLE', 'DESCRIPT']);
        $rs       = (new Fourniss($this->pdo))->find(['CODE' => $idFrs], ['RS'])['RS'] ?? '';

        if (!$visu) {
            $title = \Helpers\Trad\Trad::strBuild($trad->t('Saisie des réponses pour le fournisseur @1@ (@2@) dans la campagne : @3@ (@4@)'), $rs, $idFrs, $infoCamp['LIBELLE'], $idcamp);
            if ($user) {
                $arianeTitle = $trad->t('Réponse');
            } else {
                $arianeTitle = $trad->t('Saisie réponse');
            }
        } else {
            $title       = \Helpers\Trad\Trad::strBuild($trad->t('Visualisation des réponses pour le fournisseur @1@ (@2@) dans la campagne : @3@ (@4@)'), $rs, $idFrs, $infoCamp['LIBELLE'], $idcamp);
            $arianeTitle = $trad->t('Visualisation réponse');
            $canEdit     = false;
        }

        Ariane::generate(2, $arianeTitle, $post);

        if ($this->typeConnexionExterne && $externeUrl == 0) {
            $externe = true;
            $layout  = 'layout-externe.twig';
        } else {
            $externe = false;
            $layout  = 'layout.twig';
        }

        return $this->renderer->render('@Evaluation/Evaluation/saisieReponse', [
            'menuActive' => Session::verifySessionTypeMenuTop(MenuTopEnum::S2C) ? 'Consultations' : 'Evaluations',
            'menuLeft' => 'ratings',
            'listeQuestion' => $listeQuestion,
            'idFrs' => $idFrs,
            'listeThemeCamp' => $listeThemeCampTmp,
            'titre' => $title,

            'rs' => $rs,
            'idcamp' => $idcamp,
            'listeQuestionPropose' => $listeQuestionPropose,
            'commentaireGlobal' => $commentaireGlobal,
            'layout' => $layout,
            'infoCamp' => $infoCamp,
            'externe' => $externe,
            'canEdit' => $canEdit,
            'visu' => $visu,
            'modeErreur' => true,
            'isDepouilleur' => $isDepouilleur
        ]);
    }


    /**
     * saisieDeReponseVisuAction
     *
     *  @return string
     */
    public function saisieDeReponseVisuAction()
    {
        $post   = $this->request->getParsedBody();
        $idcamp = $this->request->getAttribute('idCamp');
        $idFrs  = $this->request->getAttribute('idFrs');
        $visu   = $this->request->getAttribute('visu');
        $user   = $this->request->getAttribute('user');
        $post   = $this->request->getParsedBody();

        return $this->saisieDeReponseAction($post + ['user_visu' => $user], $idcamp, $idFrs, $visu ? true : false);
    }

    /**
     * ajaxUpdateValueAction
     *
     * @return \GuzzleHttp\Psr7\Response
     */
    public function ajaxUpdateValueAction()
    {
        $idCamp = $this->request->getAttribute('idCamp');
        $idFrs  = $this->request->getAttribute('idFrs');

        $post = $this->request->getParsedBody();

        $this->evaluationService->updateValueReponseWithNote($post, $idCamp, $idFrs);

        return new Response(200);
    }

    /**
     * ajaxUpdateValueAction
     *
     * @return \GuzzleHttp\Psr7\Response
     */
    public function ajaxResetReponseAction(): Response
    {
        $idCamp = $this->request->getAttribute('idCamp');
        $idFrs  = $this->request->getAttribute('idFrs');

        $post = $this->request->getParsedBody();

        $this->evaluationService->resetReponse($post, $idCamp, $idFrs);

        return new Response(200);
    }

    /**
     * validationReponseAction
     *
     * @return \GuzzleHttp\Psr7\Response
     */
    public function validationReponseAction()
    {
        $idCamp = $this->request->getAttribute('idCamp');
        $idFrs  = $this->request->getAttribute('idFrs');

        $this->evaluationService->validationQuestionnaire($idCamp, $idFrs, $this->typeConnexionExterne, $this->router, $this->contenaire, $this->JWTKEY);

        /**
         *  Redirection
         */
        if ($this->typeConnexionExterne == true) {
            $payload = [
                'ID_NOTEUR' => $_SESSION['Session_Login'],
                'EMAIL_NOTEUR' => $_SESSION['email'],
                'exp' => time() + 60 * 60 * 60 * 60
            ];
            $path    = $this->router->generateUri(
                'Evaluation.Evaluation.index',
                ['jwt' => \Firebase\JWT\JWT::encode($payload, $this->JWTKEY, 'HS256')]
            );
        } else {
            $path = $this->router->generateUri('Evaluation.Evaluation.index');
        }

        return new Response(200, [], (string) json_encode(['path' => $path, 'statut' => 'O']));
    }

    /**
     * questionDependanteAction
     *
     * @return string
     */
    public function questionDependanteAction(): string
    {
        $idCamp = $this->request->getAttribute('idCamp');
        $idFrs  = $this->request->getAttribute('idFrs');

        $post                  = $this->request->getParsedBody();
        $noDep                 = [];
        $tmpQuestionDependante = $this->evaluationService->getQuestionDependante($post, $idCamp, $idFrs, $noDep, $this->contenaire, $this->router, $this->JWTKEY);

        return $this->renderer->render('@Evaluation/Evaluation/questionsDependantes', [
            'idFrs' => $idFrs,
            'idcamp' => $idCamp,
            'listeQuestionPropose' => $tmpQuestionDependante,
            'noDep' => $noDep
        ]);
    }

    /**
     * popupValidationIfDependanceAction
     *
     * @return string
     */
    public function popupValidationIfDependanceAction(): string
    {
        $post    = $this->request->getParsedBody();
        $path    = $post['Path'];
        $message = $post['Message'];
        $idCamp  = $post['Entity'] ?? '';
        $idFrs   = $post['option'] ?? '';
        $form    = $post['form'] ?? '';
        $html    = '';
        $trad    = $this->getTranslationService();

        $error = $this->evaluationService->getError($idFrs, $idCamp, $trad, $this->typeConnexionExterne);

        if ($error == '') {
            $html = $this->evaluationService->getDependanceForPopup($trad, $idCamp);
        }

        return $this->renderer->render('@Evaluation/Evaluation/confirmationValidation', [
            'message' => $message . $html,
            'pathURL' => $path,
            'form' => $form,
            'error' => $error
        ]);
    }

    /**
     * Summary of notationDepouilleurAction
     * @param \Entity\Model\CampEnt $campEnt
     * @return Response|string
     */
    public function notationDepouilleurAction(
        CampEnt $campEnt,
        CampQstQ $campQstQ,
        CampEve $campEve
    ): string|Response {
        $post        = $this->request->getParsedBody();
        $idCamp      = $this->request->getAttribute('idCamp');
        $fromCloture = $this->request->getAttribute('fromCloture') ?? 0;
        $user        = User::getUser()->getCodeUser();
        $trad        = $this->getTranslationService();

        if (count($post) > 0) {
            foreach ($post as $key => &$value) {
                $infos = explode('-', $key);
                if ($value < 0 || $value > 10) {
                    $questionName = $campQstQ->find([
                        'ID_CAMP' => (int) $idCamp,
                        'ID_THEME' => $infos[1],
                        'ID_QUEST' => (int) $infos[2],
                    ])['LIB_QUEST'];
                    return new Response(200, [], $this->renderer->render('@popup-erreur/erreurAlerteEtAvertissement', [
                        'params' => [
                            'titrePopup' => $this->getTranslationService()->t('La note saisie n\'est pas valide.'),
                            'alerte' => \Helpers\Trad\Trad::strBuild($trad->t('La note saisie pour la réponse à la question "@1@" doit être comprise entre 0 et 10.'), $questionName),
                        ]
                    ]));
                }
                $updated = $this->evaluationService->updateNoteValidationDepouilleur($idCamp, $infos[1], $infos[2], $infos[3], $infos[4], $value);
                if (!$updated) {
                    return new Response(200, [], $this->renderer->render('@popup-erreur/erreurAlerteEtAvertissement', [
                        'params' => [
                            'titrePopup' => $this->getTranslationService()->t('Une erreur est survenue.'),
                            'alerte' => $trad->t('Une erreur est survenue, merci de contacter votre administrateur.'),
                        ]
                    ]));
                }
                unset($post[$key]);
            }
            $getMaxNumEve = $campEve->getMaxNumEve($idCamp);
            $campEve->insert([
                "ID_CAMP" => (int) $idCamp,
                "NUM_ORDR" => $getMaxNumEve + 1,
                "DTE_EVE" => date("Ymd"),
                "HEU_EVE" => date("His"),
                "ID_USER" => User::getUser()->getCodeUser(),
                "COD_EVE" => "DEP",
                "COMMENT" => "",
                "COMMENTAIRE" => ""
            ]);

            switch (intval($fromCloture)) {
                case 1:
                    return new Response(200);
                default:
                    return new Response(301, [], (string) \json_encode([
                        'path' => $this->router->generateUri('Evaluation.Campaign.index'),
                        'post' => (array) $post,
                    ]));
            }
        }

        // Depouilleur = créateur de l'éval
        if ($campEnt->find(['ID_CAMP' => $idCamp])['CREEEPAR'] !== $user) {
            return $this->redirect('Evaluation.Campaign.index');
        }

        $listeThemeCampTmp = $listeQuestion = $listeQuestionPropose = [];

        $this->evaluationService->controleThemeEtQuestionPourDepouilleur(
            $listeThemeCampTmp,
            $listeQuestion,
            $listeQuestionPropose,
            $idCamp,
            $externeForm,
            $user,
        );

        if (count($listeQuestion) <= 0) {
            return $this->redirect('Evaluation.Campaign.index');
        }

        $title    = $trad->t('Saisie des notations par le dépouilleur');
        $infoCamp = $campEnt->find(['ID_CAMP' => $idCamp], ['LIBELLE', 'DESCRIPT']);

        Ariane::generate(1, $trad->t('Notation dépouilleur'), $post);

        return $this->renderer->render('@Evaluation/Evaluation/notationDepouilleur', [
            'menuActive' => Session::verifySessionTypeMenuTop(MenuTopEnum::S2C) ? 'Consultations' : 'Evaluations',
            'menuLeft' => 'ratings',
            'listeQuestion' => $listeQuestion,
            'listeThemeCamp' => $listeThemeCampTmp,
            'titre' => $title,
            'idcamp' => $idCamp,
            'listeQuestionPropose' => $listeQuestionPropose,
            'infoCamp' => $infoCamp,
            'modeErreur' => true,
            'isDepouilleur' => true,
            'fromCloture' => $fromCloture
        ]);
    }

    /**
     * Summary of ajaxResetNoteAction
     * @return Response
     */
    public function ajaxUpdateNoteAction(): Response
    {
        $idCamp = $this->request->getAttribute('idCamp');

        $post = $this->request->getParsedBody();

        $this->evaluationService->updateNote($post, $idCamp, $post['codeFou'], $post['codNoteur']);

        return new Response(200);
    }
}
