<?php
namespace Modules\Administration\Controller;

use Entity\Model\Alias\ParamUtilisateur;
use Entity\Model\Hastutil;
use Entity\Model\Paravrac;
use Entity\Model\PrOxaCat;
use Entity\Model\Utilcreate;
use Helpers\Ariane\Ariane;
use Helpers\Fichier\Fichier;
use Helpers\Outil\Roles;
use Helpers\Outil\Sql;
use Helpers\Outil\StringHelper;
use Helpers\Pagination\PaginatorGestion;
use Helpers\Trad\Trad;
use Helpers\Validator\FormValidator;
use Modules\Administration\Repository\UtilisateurRepo;
use Modules\Administration\Service\FormUtilisateur;
use Modules\Commande\WebService\Commande;
use Modules\Index\WebService\UtilisateurWsdl;
use Skeleton\Controller\Controller;
use GuzzleHttp\Psr7\Response;

class GestionUtilisateurController extends Controller
{
    public function getWsdl() :UtilisateurWsdl
    {
        return new UtilisateurWsdl($this->contenaire);
    }

    public function getRepository() :UtilisateurRepo
    {
        return new UtilisateurRepo($this->pdo);
    }

    public function getFormService() :FormUtilisateur
    {
        return new FormUtilisateur($this->pdo);
    }

    public function listPendingCreationAction() : string
    {
        $post = $this->request->getParsedBody();
        
        if (empty($post)) {
            $post = ['tri_NOM' => 'asc'];
        }

        $repo = $this->getRepository();
        $list = $repo->listDemCreation($_SESSION['Session_Login'], $post);

        return $this->renderer->render('@Administration/GestionUtilisateur/listPendingRegistration', [
            'listItem' => $list,
            'current_route' => $this->router->getNameRoute(),
            'infoPagination' => PaginatorGestion::getInfoPagination(),
            'mapCount' => $repo->getCountRegistration(
                ['C', 'M'],
                $_SESSION['Session_Login']
            ),
            'post' => $post,
        ]);
    }

    public function listPendingModifAction() : string
    {
        $post = $this->request->getParsedBody();
        
        if (empty($post)) {
            $post = ['tri_NOM' => 'asc'];
        }
        
        $repo = $this->getRepository();
        $list = $repo->listDemModif($_SESSION['Session_Login'], $post);

        return $this->renderer->render('@Administration/GestionUtilisateur/listPendingModif', [
            'listItem' => $list,
            'current_route' => $this->router->getNameRoute(),
            'infoPagination' => PaginatorGestion::getInfoPagination(),
            'mapCount' => $repo->getCountRegistration(
                ['C', 'M'],
                $_SESSION['Session_Login']
            ),
            'post' => $post,
        ]);
    }

    public function listCollabAction() : string
    {
        $post = $this->request->getParsedBody();

        if (empty($post)) {
            $post = ['tri_NOM' => 'asc'];
        }

        $repo = $this->getRepository();
        $list = $repo->listCollab($_SESSION['Session_Login'], $post);

        return $this->renderer->render('@Administration/GestionUtilisateur/listUser', [
            'listItem' => $list,
            'current_route' => $this->router->getNameRoute(),
            'infoPagination' => PaginatorGestion::getInfoPagination(),
            'mapCount' => $repo->getCountRegistration(
                ['C', 'M'],
                $_SESSION['Session_Login']
            ),
            'post' => $post,
        ]);
    }

    public function listUserBlockedAction() : string
    {
        $post = $this->request->getParsedBody();

        if (empty($post)) {
            $post = ['tri_NOM' => 'asc'];
        }

        $repo = $this->getRepository();
        $list = $repo->listBlocked($_SESSION['Session_Login'], $post);
        
        return $this->renderer->render('@Administration/GestionUtilisateur/listBlocked', [
            'listItem' => $list,
            'current_route' => $this->router->getNameRoute(),
            'infoPagination' => PaginatorGestion::getInfoPagination(),
            'mapCount' => $repo->getCountRegistration(
                ['C', 'M'],
                $_SESSION['Session_Login']
            ),
            'post' => $post,
        ]);
    }
    
    public function formEditUserAction() : string
    {
        $userId = $this->request->getAttribute('userId');
        $user = $this->getRepository()->getUser($userId);
        return $this->renderer->render('@Administration/GestionUtilisateur/pageFormEditUser', [
            'subject' => $user,
            'form' => $this->getFormService()->getFormEdit(),
            'user' => [
                'SIG_DA' => Sql::toBool($user['SIG_DA']),
                'SIG_CDE' => Sql::toBool($user['SIG_CDE']),
                'SIG_BAP' => Sql::toBool($user['SIG_BAP']),
            ] + $user,
        ]);
    }

    public function editUserAction() : Response
    {
        $userId = $this->request->getAttribute('userId');
        $post = $this->request->getParsedBody();
        $trad = $this->getTranslationService();

        foreach ($this->request->getUploadedFiles() as $k => $file) {
            $post[ StringHelper::removePrefix($k, 'import') ] = $file;
        }

        $validator = $this->createFormValidator();
        $formService = $this->getFormService();
        $data = $validator->validateForm(
            $formService->getView(
                $trad,
                $formService->getFormEdit()
            ),
            $post
        );
        if (! $validator->isValid()) {
            return new Response(400, [], $validator->getError());
        }
        $response = $this->getWsdl()->updateUser($userId, $data);
        if ($response->Retour != 'Workflow') {
            return new Response(400, [], (string) $response->MsgErreur);
        }

        return new Response(200);
    }

    public function formApprobDemAction() : string
    {
        $demId = $this->request->getAttribute('demId');
        $dem = (new Utilcreate($this->pdo))->find($demId);
        if (empty($dem)) {
            return 'Invalid demand id';
        }

        // Case : user comming form email link
        // In order to support the ariane back
        if (! Ariane::hasLevel(0)) {
            Ariane::generate(
                0,
                'Tableau de bord',
                [],
                null,
                $this->router->generateUri('Index.Index.index')
            );
        }

        return $this->renderer->render('@Administration/GestionUtilisateur/pageFormDemApprob', [
            'subject' => $this->getRepository()->getDem($demId),
            'form' => $this->getFormService()->getFormApprob(),
            'formStep2' => array_column(array_filter([
                (new Paravrac($this->pdo))->hasSignPassword() ?
                    (object) ['type' => 'PASSWORD', 'name' => 'password'] : null,
                $dem['CREATMOD'] == 'C'/* Creation */ && Roles::isAdmin() ?
                    (object) ['type' => 'TEXT', 'name' => 'login'] : null,
            ]), null, 'name'),
        ]);
    }

    public function approveDemAction() : Response
    {
        $demId = $this->request->getAttribute('demId');
        $post = $this->request->getParsedBody();
        foreach ($this->request->getUploadedFiles() as $k => $file) {
            $post[ StringHelper::removePrefix($k, 'import') ] = $file;
        }
        $dem = (new Utilcreate($this->pdo))->find($demId);
        $trad = $this->getTranslationService();

        // Fail safe
        if (empty($dem)) {
            return new Response(400, [], 'Invalid dem #'.$demId);
        }

        //___________________
        // Validate
        
        $validator = $this->createFormValidator();
        $validator->ignorePerimetre(true);
        $formService = $this->getFormService();
        $data = $validator->validateForm(
            $formService->getView(
                $this->getTranslationService(),
                $formService->getFormApprob()
            ),
            $post
        );

        if ($dem['CREATMOD'] == 'C'/* Creation */ && Roles::isAdmin()) {
            $validator->isCode(
                $trad->t('Login'),
                $post['login'],
                1,
                30
            );

            $validator->entityAlreadyExist(
                Trad::strBuild(
                    $trad->t('@1@ avec le code @2@ existe déjà.'),
                    $trad->t('L’utilisateur'),
                    $post['login']
                ),
                new Hastutil($this->pdo),
                $post['login']
            );
            $data['login'] = $post['login'];
        }

        if ((new Paravrac($this->pdo))->hasSignPassword()) {
            $validator->isStringAvecEspace($trad->t('Mot de passe'), $post['password'], 1);
            $data['password'] = $post['password'];
        }

        if (! $validator->isValid()) {
            return new Response(400, [], $validator->getError());
        }

        //___________________
        // Process
        
        $ws = $this->getWsdl();
        $response = $ws->updateDemUser($dem['USR_MOD'], $data, $demId);

        if ($response->Retour != 'Workflow') {
            return new Response(400, [], (string) $response->MsgErreur);
        }

        // Si le wdsl de modification est OK alors on valide la création de compte
        $response = $ws->approbDemUser(
            $demId,
            $data['password'] ?? '',
            $data['login'] ?? ''
        );

        if ($response->Statut != 'O') {
            return new Response(400, [], (string) $response->MsgErreur);
        }

        return new Response(200);
    }

    public function detailAction() :string
    {
        $userId = $this->request->getAttribute('userId');
        $paravrac = new ParamUtilisateur($this->pdo);
        return $this->renderer->render('@Administration/GestionUtilisateur/_detail', [
            'user' => $this->getRepository()->getUser($userId),
            'isSupHierActive' => $paravrac->hasSupHierChoice(),
            'isUOActive' => $paravrac->hasUOChoice(),
            'isPubGenerique' => (new PrOxaCat($this->pdo))->isPublicationGeneric(),
        ]);
    }

    /**
     * @return Response|string
     */
    public function userImgSignatAction()
    {
        $userId = $this->request->getAttribute('userId');
        $reponse = Commande::previewImgSignOnCde($userId);
        if ($reponse->Statut == 'E') {
            return new Response(404, [], 'Fichier introuvable');
        }

        return Fichier::UploadClient($reponse->FichierPDF, 'Signature.pdf');
    }


    public function refusDemAction() : Response
    {
        $demId = $this->request->getAttribute('demId');
        $post = $this->request->getParsedBody();
        $trad = $this->getTranslationService();
        $dem = (new Utilcreate($this->pdo))->find($demId);
        if (empty($dem)) {
            return new Response(404, [], '');
        }

        $validator = $this->createValidator();

        $validator->isStringAvecEspace(
            $trad->t('Commentaires associés au refus'),
            $post['comment'],
            1,
            3000
        );
        if ((new Paravrac($this->pdo))->hasSignPassword()) {
            $validator->isStringAvecEspace($trad->t('Mot de passe'), $post['password'], 1);
        }

        if (! $validator->isValid()) {
            return new Response(400, [], $validator->getError());
        }

        $response = $this->getWsdl()->refusDemUser(
            $demId,
            $post['password'] ?? '',
            $post['comment']
        );

        if ($response->Statut != 'O') {
            return new Response(400, [], (string) $response->MsgErreur);
        }

        return new Response(200);

        // TODO : flashbag
        // if (getValue('sign_or_refuse') == 'S') // Si signature
        //     if (getValue('mode') == 'C')
        //         $msg = trad('La validation de création du compte est prise en compte');
        //     else
        //         $msg = trad('La validation de demande de modification du compte est prise en compte');
        // elseif (getValue('sign_or_refuse') == 'R') // Si refus
        //     if (getValue('mode') == 'C')
        //         $msg = trad('Le refus de création du compte est pris en compte');
        //     else
        //         $msg = trad('Le refus de modification de compte est pris en compte');
    }

    public function unblockAction() : Response
    {
        $userId = $this->request->getAttribute('userId');

        $response = $this->getWsdl()->unblock($userId);
        if ($response->Statut == 'E') {
            return new Response(400, [], $response->Erreur);
        }
        return new Response(200);
    }

    
    public function testeSMTPAction() : Response
    {
        return $this->testSmtp($this->request->getParsedBody());
    }

    /**
     * @param array<mixed> $post
     */
    public function testSmtp(array $post): Response
    {
        $trad = $this->getTranslationService();
        $validator = $this->createValidator();
        $validator->isStringAvecEspace($trad->t('Code utilisateur'), $post['login'], 1, 2000);
        $validator->isStringAvecEspace($trad->t('Mot de passe'), $post['password'], 1, 2000);
        $validator->adresseMail($trad->t('Adresse mail'), $post['email'], 1, 100);

        if (! $validator->isValid()) {
            return new Response(400, [], $validator->getError());
        }
        
        $res = $this->getWsdl()->callWSDLForTestSMTP(
            $post['login'],
            $post['password'],
            $post['email'],
            $trad
        );
        $response = new \SimpleXMLElement($res->responseData);

        if ($response->Retour != 'O') {
            return new Response(400, [], (string) $response->MsgErreur);
        }
        return new Response(200, [], $trad->t('Un mail de test vous a été envoyé. Si vous ne le recevez pas, cela indique que votre paramétrage est incorrect.'));
    }
}
