<?php
namespace Modules\Utilisateur\Controller;

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

class ProfileController 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 suiviCompteAction():string
    {
        $paravrac = new ParamUtilisateur($this->pdo);

        $emailLogin = $_SESSION['ID_TMP']??'';
        
        $repo       = $this->getRepository();
        $user       = $repo->getInscription($emailLogin);

        $statut = 1;
        $statutForInscription = $repo->getStatusForInscription($emailLogin);
        $infoInscription = (new Utilcreate($this->pdo))->find(['EMAIL' => $emailLogin]);
        $accountExist = (new Hastutil($this->pdo))->find(['EMAIL' => $emailLogin]);
        if ($statutForInscription) {
            $statut = 2;
        } elseif ($infoInscription) {
            $statut = 3;
        } elseif ($accountExist) {
            $statut = 4;
        }

        return $this->renderer->render('@Utilisateur/Profile/SuiviCompte', [
            'user' => $user,
            'hasSmtpChoice' => $paravrac->hasSmtpChoice(),
            'hasSupHierChoice' => $paravrac->hasSupHierChoice(),
            'hasUOChoice' => $paravrac->hasUOChoice(),
            'hasModuleEproc' => Roles::isAdmin() || $paravrac->hasEprocDemande(),
            'statut'    => $statut,
        ]);
    }
    

    public function formEditAction() : string
    {
        $userId = $_SESSION['Session_Login'];
        $repo = $this->getRepository();
        $user = $repo->getUser($userId);
        $formService = $this->getFormService();
        
        $demModif = $repo->getDemModif($userId);
        // Case : Profile is no longer modifiable if a Demande already exist
        if (!empty($demModif)) {
            $paravrac = new ParamUtilisateur($this->pdo);
            return $this->renderer->render('@Utilisateur/Profile/detailProfil', [
                'user' => $user,
                'formPassword' => $formService->getFormPassword($this->contenaire),
                'hasSmtpChoice' => $paravrac->hasSmtpChoice(),
                'hasSupHierChoice' => $paravrac->hasSupHierChoice(),
                'hasUOChoice' => $paravrac->hasUOChoice(),
                'hasModuleEproc' => Roles::isAdmin() || $paravrac->hasEprocDemande(),
                'isPasswordForSignActivated' =>
                    (new ParamUtilisateur($this->pdo))->isPasswordForSignActivated(),
            ]);
        }

        return $this->renderer->render('@Utilisateur/Profile/formProfil', [
            'hasBackup' => roles::droitsUtilisateur($this->pdo, 'OX_AF_BACK'),
            'modeModif' => true,

            'subject' => $user,
            'formPassword' => $formService->getFormPassword($this->contenaire),
            'formUser' => $formService->getFormProfileEdit(),
            'user' => [
                'SIG_DA' => Sql::toBool($user['SIG_DA']),
                'SIG_CDE' => Sql::toBool($user['SIG_CDE']),
                'SIG_BAP' => Sql::toBool($user['SIG_BAP']),
                'onlyProfil' => !$_SESSION['ConnexionEproc'],
            ] + $user,
            'isPasswordForSignActivated' =>
                (new ParamUtilisateur($this->pdo))->isPasswordForSignActivated(),
            'menuActive' => '',
            'menuLeft' => '',
        ]);
    }

    public function editPasswordAction() :Response
    {
        $type = $this->request->getAttribute('type');
        $post = $this->request->getParsedBody();
        $paravrac = new ParamUtilisateur($this->pdo);

        //___________________

        $validator = $this->createValidator();
        if ($type != 'signat') {
            $validator->isPassword($post['new_pass'], $this->pdo);
        }
        $nbrTentativeMax = intval($paravrac->getGeneric('MDPNBCONNECT') ?? 0);

        $_SESSION['tentativeMdp'] = $_SESSION['tentativeMdp'] ?? 0;

        if ($nbrTentativeMax > 0 && $nbrTentativeMax <= $_SESSION['tentativeMdp']) {
            $trad = $this->getTranslationService();
            return new Response(400, [], $trad->t('Nombre de tentatives épuisé.'));
        }

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

        //___________________
        // Process

        $reponse = $this->getWsdl()->changePassword(
            $_SESSION['Session_Login'],
            $post['pass'],
            $post['new_pass'],
            $type == 'signat'
        );
        if ($reponse->Statut != 'O') {
            $_SESSION['tentativeMdp']++;
            return new Response(400, [], (string)$reponse->Erreur);
        }

        $_SESSION['tentativeMdp'] = 0;
        return new Response(200, []);
    }

    public function editAction() :Response
    {
        $userId = $_SESSION['Session_Login'];
        $post = $this->request->getParsedBody();
        foreach ($this->request->getUploadedFiles() as $k => $file) {
            $post[ $k ] = $file;
        }
        $trad = $this->getTranslationService();
        $repo = $this->getRepository();

        //___________________
        // Validation

        if (! empty($repo->getDemModif($userId))) {
            return new Response(
                400,
                [],
                $trad->t('Vous avez une demande de modification actuellement en cours, vous pourrez modifier à nouveau votre compte après sa validation.')
            );
        }

        $validator = new FormValidator($this->pdo, $this->getTranslationService());
       
        $formService = $this->getFormService();
        $form = $formService->getFormProfileEdit();
        $data = $validator->validateForm(
            $formService->getView($trad, $form),
            $post
        );
        if (! $validator->isValid()) {
            return new Response(400, [], $validator->getError());
        }

        //___________________
        // Process

        $ws = $this->getWsdl();
        if ($this->isApprobRequired(
            $form,
            $repo->getUser($userId),
            $data
        )) {
            $resp = $ws->createDemModifUser($userId, $data);
        } else {
            $resp = $ws->updateUser($userId, $data);
        }

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

//_____________________________________________________________________________
// Sub-routine

    /**
     * @param array<string|int,\stdClass> $form
     * @param array<mixed> $oldUser
     * @param array<mixed> $newUser
     */
    public function isApprobRequired(array $form, array $oldUser, array $newUser) :bool
    {
        foreach (array_filter($form, function ($input) {
            return ($input->approbRequired ?? false)
                && !($input->disabled ?? false);
        }) as $input) {
            if ($oldUser[ $input->name ] != $newUser[ $input->name ]) {
                return true;
            }
        }
        return false;
    }
}
