<?php
namespace Modules\Utilisateur\Controller;

use Entity\Model\Alias\ParamUtilisateur;
use Entity\Model\Hastutil;
use Entity\Model\Paravrac;
use GuzzleHttp\Psr7\Response;
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 formEditAction() : string
    {
        $userId = $_SESSION['Session_Login'];
        $repo = $this->getRepository();
        $user = $repo->getUser($userId);
        $formService = $this->getFormService();
        
        $demModif = $repo->getDemModif($userId);
        if (!empty($demModif)) {
            $paravrac = new ParamUtilisateur($this->pdo);
            return $this->renderer->render('@Utilisateur/Profile/detailProfil', [
                'user' => $user,
                'formPassword' => $formService->getFormPassword(),
                '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', [
            'subject' => $user,
            'formPassword' => $formService->getFormPassword(),
            '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']),
            ] + $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);

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

        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, [], $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;
        }

        //___________________
        // Validation

        $validator = new FormValidator($this->pdo, $this->getTranslationService());

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

        //___________________
        // Process

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

        if ($resp->Statut != 'O') {
            return new Response(400, [], $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;
        }) as $input) {
            if ($oldUser[ $input->name ] != $newUser[ $input->name ]) {
                return true;
            }
        }
        return false;
    }
}
