<?php
namespace Modules\Signature\Controller;

use Entity\Model\CaPijo;
use Entity\Model\Codgest;
use Entity\Model\Paramnum;
use Entity\Model\Paravrac;
use Entity\Model\PJTypes;
use Entity\Model\Sectimpu;
use GuzzleHttp\Psr7\Response;
use Helpers\Ariane\Ariane;
use Helpers\Ariane\ArianeSub;
use Helpers\ChampsSupplementaire\ChampSupp;
use Helpers\Outil\Roles;
use Helpers\Outil\Sql;
use Helpers\Session\InitSession;
use Helpers\Trad\Trad;
use Modules\Commande\Repository\Commande;
use Modules\Signature\MenuContextuel\SignatureCdeMenuContextuel;
use Modules\Signature\Repository\CdeSignRepository;
use Modules\Suivi\Repository\SuiviCdeRepo;
use Modules\Suivi\Service\SuiviService;
use Skeleton\Controller\Controller;
use Firebase\JWT\Key;
use Modules\GlobalApplication\Repository\Signature;

class SignatureCdeController extends AbsSignatureController
{
    /**
     * @var string $menuActive
     */
    public $menuActive;

    public function init() : void
    {
        if ($_SESSION['typeMenu'] == 'P2P') {
            $this->menuActive = 'eproc';
        } else {
            $this->menuActive = 'CollecteBesoins';
        }
    }

    public function listeDocAction() : string
    {
        $post = $this->request->getParsedBody();
        $signataire = $this->request->getAttribute('signataire');

        $trad = $this->getTranslationService();

        $droit = [
            'HA_CA_VEV' => Roles::droitsUtilisateur($this->pdo, 'HA_CA_VEV', $_SESSION["Session_Login"]),

            'HA_SE_CHSI' => Roles::droitsUtilisateur($this->pdo, 'HA_SE_CHSI', $_SESSION["Session_Login"]),
            'HA_SE_SATT' => Roles::droitsUtilisateur($this->pdo, 'HA_SE_SATT', $_SESSION["Session_Login"]),
            'HA_SE_AJSI' => Roles::droitsUtilisateur($this->pdo, 'HA_SE_AJSI', $_SESSION["Session_Login"]),
        ];

        if (!$post) {
            $post = ['tri_NO_CDE' => 'asc'];
        }

        $listeCommande = (new CdeSignRepository($this->pdo))->listTobeSigned($post, $signataire);

        $menuContextuel = new SignatureCdeMenuContextuel($this->pdo, $this->router, $this->getTranslationService(), $droit);
        foreach ($listeCommande as &$cde) {
            $cde['menuContextuel'] = $menuContextuel->generate($cde, $signataire);
        }

        Ariane::generate($signataire ? 1 : 0, $trad->t('Signature'), $post, count($listeCommande));

        $paginator = new \Helpers\Pagination\Paginator();
        $infopagination = $paginator->generate($listeCommande, 0, $post, $this->renderer);

        return $this->renderer->render('@signature/Commande/listeDoc', [
            'menuActive'        => $this->menuActive,
            'signataire'        => $signataire,
            'post'              => $post,
            'infoPagination'    => $infopagination,
            'listeCde'          => $listeCommande,
            'login'             => $_SESSION['Session_Login'],
            'societe'           => $_SESSION['Session_SocUsr'],
            'droit'             => $droit,
            'param'             => (new SuiviService($this->pdo, $trad))->getParametrageSuivi(),
            'delegAbs'          => (new Signature($this->pdo))->countDelegABS()['count']??0
        ]);
    }

    public function ajoutSignataireAction() : string
    {
        $numCde = $this->request->getAttribute('idDoc');
        $post   = $this->request->getParsedBody();
        $trad = $this->getTranslationService();
        
        $repo_Signa = new CdeSignRepository($this->pdo);

        
        if ($post) {
            foreach ($post as $key => $value) {
                $tblKey = explode('_', $key);
                if (count($tblKey)==2) {
                    if ($post[$tblKey[0].'_6']=='N' && $key==$tblKey[0].'_6') {
                        $array=[
                            'SIGNAT' => $post[$tblKey[0].'_3'],
                            'NO_CDE' => $numCde,
                            'DTE_MISE' => date('Ymd'),
                            'ORDRE' => round($post[$tblKey[0].'_0']),
                            'SIGNABLE' => true,
                            'INFORME' => $post[$tblKey[0].'_5'] == 'N' ? false:true,
                            'CAROLES' => $post[$tblKey[0].'_2'],
                        ];
                        $repo_Signa->insertNewSignat($array);
                    }
                }
            }
            
            return $this->renderer->render('@popup-erreur/confirmationGestion', [
                'message' => $trad->t('Vos signataires ont été ajoutés.'),
                'refresh' => true,
                'div_refresh' => 'commandes',
                'iconePopup' => 'information',
            ]);
        }
        
        $signataires = new \Modules\Ajax\Repository\Signataires($this->pdo);
        $signataire = $signataires->signataireCde((int)$numCde);
        
        foreach ($signataire as $key => $value) {
            $listeSignataires[$value['CODE']]=$value['NOM'];
        }
        
        
        $Signa = $repo_Signa->listeSignat($numCde);
        
        $listeSigna='';
        foreach ($Signa as $value) {
            if ($listeSigna) {
                $listeSigna .= '|'.$value['ORDRE'].';;'.$value['CAROLES'].';'.$value['SIGNAT'].';'.$value['NOM'].';'.(Sql::boolSql($value['INFORME']) ? 'O':'N').';O;';
            } else {
                $listeSigna .= $value['ORDRE'].';;'.$value['CAROLES'].';'.$value['SIGNAT'].';'.$value['NOM'].';'.(Sql::boolSql($value['INFORME']) ? 'O':'N').';O;';
            }
        }
        $erreurValid['AlgoSpecif'] = $listeSigna;

        $droits['ajoutSignataire'] = \Helpers\Outil\Roles::droitsUtilisateur($this->pdo, 'HA_SE_AJSI');
        $droits['suppressionSignataire'] = \Helpers\Outil\Roles::droitsUtilisateur($this->pdo, 'HA_SE_SUSI');
        
        return $this->renderer->render('@popup-erreur/signataireXml', [
            'listeTypeRole'    => ['N' => $trad->t('Signataire'), 'O' => $trad->t('Informé')],
            'listeSignataires' => $listeSignataires??[],
            'ErreurValid' => $erreurValid,
            'pathValidation' => $this->router->generateUri('Signature.SignatureCde.ajoutSignataire', ['idDoc' => $numCde]),
            
            'droits'              => $droits,
        ]);
    }

    public function editAndSignAction() : string
    {
        $numCde = $this->request->getAttribute('idDoc');
        $signataire = $this->request->getAttribute('signataire');

        $trad = $this->getTranslationService();

        $infoEntete = (new SuiviCdeRepo($this->pdo, $this->router, $trad))->getInfoEntete($numCde);
        $listeLigne = (new SuiviCdeRepo($this->pdo, $this->router, $trad))->getLiseLigne($numCde);

        $listePJTMP = (new CaPijo($this->pdo))->fetchAll([], ['filter_egal_NO_CA' => $numCde]);
        $listePJ    = [];

        $typePj = (new PJTypes($this->pdo))->fetchAll();
        
        $listeTypePj = [];
        foreach ($typePj as $value) {
            $listeTypePj[$value['PJ_TYPE']] = $value['PJLIBELLE'];
        }

        foreach ($listePJTMP as $pj) {
            if (Sql::boolSql($pj['ISSU_TAC']) == false && $pj['NOM_FIC'] != '' && file_exists($_SESSION['chemin_pj'] . $pj['NOM_FIC'])) {
                $listePJ[] = $pj;
            }
        }

        Ariane::generate($signataire? 2:1, $trad->t('Modifier & signer'));
        Ariane::setFocus($numCde);

        return $this->renderer->render('@signature/Commande/editAndSign', [
            'menuActive'        => $this->menuActive,
            'signataire'        => $signataire,
            'infoEntete'        => $infoEntete,
            'listeLigne'        => $listeLigne,
            'listePJ'           => $listePJ,
            'numCde'            => $numCde,
            'tableau_pj'        => $listeTypePj,
            'impConfig'         => (new Paravrac($this->pdo))->getCommandeAxeImpConfig(),
            'parametrage'       => [
                'MDP_SIG' => (new Paravrac($this->pdo))->getGeneric('PAS_DE_MDP_SIG') != 'O'
            ],
        ]);
    }

    /**
     * @return Response|void
     */
    public function validationAction()
    {
        $numCde         = $this->request->getAttribute('idDoc');
        $signataire     = $this->request->getAttribute('signataire');
        $post           = $this->request->getParsedBody();
        $validator      = $this->createValidator();
        $trad           = $this->getTranslationService();

        $postTMP = json_decode($post['dataPost'], true);
        $post = [];

        $arrayPJ = [];
        foreach ($postTMP as $v) {
            if (strpos($v['name'], 'arrayPJ_') === 0) {
                $arrayPJ[] = unserialize($v['value']);
            }
            $post[$v['name']] = $v['value'];
        }
       
        $CS             = new ChampSupp($this->pdo);
        $listeCS        = $CS->generateChampSupp('CA_LIGNE');
        $validator->setValueForWSDL(true);

        /** champs signature */
        $validator->isStringAvecEspace($trad->t('Commentaire'), $post['commentaire'] ?? '', 0, 3000);

        if ($this->isPasswordActif()) {
            $validator->isStringAvecEspace($trad->t('Mot de passe'), $post['mdpSig'] ?? '', 1, 30);
        }

        /** Champs entête */
        $idCSEntete     = ChampSupp::autoCompletCodeEnr($numCde, '', 'CA_ENTET');
        $csEntete = $validator->validatorCS('CA_ENTET', $idCSEntete, $post, $this->pdo);

        $infoEntete = (new SuiviCdeRepo($this->pdo, $this->router, $trad))->getInfoEntete($numCde);

        $codeSte = $infoEntete['CODE_STE'];

        //imputation entête
        $impConfig = (new Paravrac($this->pdo))->getCommandeAxeImpConfig();
        
        $libValid = $trad->t('Entête').$trad->colon();
        
        if ($impConfig->SectImp->isActive) {
            $cgParId = Roles::droit($this->pdo, 'CODE_GESTION_PAR_ID')? 1:0;


            $validator->zoom('Sectimpu', $post['SECTIMP'], $libValid.$trad->t('sections d\'imputation'), $this->pdo, true, $impConfig->SectImp->isSecto ?['filter_CODE_STE' => $codeSte] : []);
        
            $sectionImp = (new Sectimpu($this->pdo))->find($post['SECTIMP']);
            if ($sectionImp != null) {
                $sectionImp['SICODG'] = Sql::toBool($sectionImp['SICODG']);
                $sectionImp['IMPCODG'] = Sql::toBool($sectionImp['IMPCODG']);
            }

            if (isset($sectionImp) && ($sectionImp['SICODG']??false)) {
                $validator->codeGestionZoom($post['CODGES'], $libValid.$trad->t('code gestion'), $this->pdo, !$sectionImp['IMPCODG'], ['CODE_SI' => $post['SECTIMP'],'cgParId' => $cgParId]);
            }
        }

        if ($impConfig->CodeCompl->isActive) {
            $validator->zoom('Codecomp', $post['CODECOMP'], $libValid.$trad->t('codes complémentaires'), $this->pdo, true, $impConfig->CodeCompl->isSecto ?['filter_egal_CODE_STE' => $codeSte] : []);
        }
        if ($impConfig->SousCompteAna->isActive) {
            $validator->zoom('Sscptana', $post['SSCPTEANA'], $libValid.$trad->t('sous-comptes d\'analyse'), $this->pdo, true, $impConfig->SousCompteAna->isSecto ?['filter_egal_CODE_STE' => $codeSte] : []);
        }

        /** Ligne */
        $listeLigne = (new SuiviCdeRepo($this->pdo, $this->router, $trad))->getLiseLigne($numCde);
        $validator->setListeCS($listeCS);

        $cgParId = Roles::droit($this->pdo, 'CODE_GESTION_PAR_ID')? 1:0;

        $ligneInsert = [];
        foreach ($listeLigne as $ligne) {
            /** CS ligne */
            $idCSLigne = ChampSupp::autoCompletCodeEnr($numCde, $ligne['NO_PO'], 'CA_LIGNE');
            $csLign = $validator->validatorCS('CA_LIGNE', $idCSLigne, $post, $this->pdo);
            $ccLign = $validator->validatorCC($this->pdo, $post, $ligne['NO_PO']);

            
            //imputation ligne
            if ($impConfig->SectImp->isActive) {
                $libValid = $trad->t('Ligne').' '.$ligne['NO_PO'].$trad->colon();
    
                $validator->zoom('Sectimpu', $post['ligne_SECTIMP'.$ligne['NO_PO']], $libValid.$trad->t('sections d\'imputation'), $this->pdo, $impConfig->SectImp->isBlankAllowed, $impConfig->SectImp->isSecto ?['filter_CODE_STE' => $codeSte] : []);
            
                $sectionImp = (new Sectimpu($this->pdo))->find($post['ligne_SECTIMP'.$ligne['NO_PO']]);
                if ($sectionImp != null) {
                    $sectionImp['SICODG'] = Sql::toBool($sectionImp['SICODG']);
                    $sectionImp['IMPCODG'] = Sql::toBool($sectionImp['IMPCODG']);
                }
    
                if (isset($sectionImp) && ($sectionImp['SICODG']??false)) {
                    $validator->codeGestionZoom($post['ligne_CODGES'.$ligne['NO_PO']], $libValid.$trad->t('code gestion'), $this->pdo, !$sectionImp['IMPCODG'], ['CODE_SI' => $post['ligne_SECTIMP'.$ligne['NO_PO']],'cgParId' => $cgParId]);
                }
            }
    
            if ($impConfig->CodeCompl->isActive) {
                $validator->zoom('Codecomp', $post['ligne_CODE_COMP'.$ligne['NO_PO']], $libValid.$trad->t('codes complémentaires'), $this->pdo, $impConfig->CodeCompl->isBlankAllowed, $impConfig->CodeCompl->isSecto ?['filter_egal_CODE_STE' => $codeSte] : []);
            }
            if ($impConfig->SousCompteAna->isActive) {
                $validator->zoom('Sscptana', $post['ligne_SSCPTEANA'.$ligne['NO_PO']], $libValid.$trad->t('sous-comptes d\'analyse'), $this->pdo, $impConfig->SousCompteAna->isBlankAllowed, $impConfig->SousCompteAna->isSecto ?['filter_egal_CODE_STE' => $codeSte] : []);
            }

            if ($cgParId) {
                $codGes = (new Codgest($this->pdo))->find([
                    'CODE_GES'  => $post['ligne_CODGES'.$ligne['NO_PO']],
                    'CODE_SI'   => $post['ligne_SECTIMP'.$ligne['NO_PO']],
                ], ['CODE_AFF']);
                $post['ligne_CODGES'.$ligne['NO_PO']] = $codGes['CODE_AFF']??'';
            }

            $ligneInsert[$ligne['NO_PO']] = [
                'SECTIMP'   => $post['ligne_SECTIMP'.$ligne['NO_PO']],
                'CODECOMP'  => $post['ligne_CODE_COMP'.$ligne['NO_PO']],
                'SSCPTEANA' => $post['ligne_SSCPTEANA'.$ligne['NO_PO']],
                'CODGES'    => $post['ligne_CODGES'.$ligne['NO_PO']],

                'CS'        => $csLign,
                'CC'        => $ccLign,
            ];
        }

        if ($validator->isValid()) {
            if ($cgParId) {
                $codGes = (new Codgest($this->pdo))->find([
                    'CODE_GES'  => $post['CODGES'],
                    'CODE_SI'   => $post['SECTIMP']
                ], ['CODE_AFF']);
                $post['CODGES'] = $codGes['CODE_AFF']??'';
            }

            $arraySign = [
                'password' => $post['mdpSig'],
                'commentaire' => $post['commentaire'],
                'mode' => 'S', // on appelle une première fois le WSDL en mode modif
                'SECTIMP'   => $post['SECTIMP'],
                'CODECOMP'  => $post['CODECOMP'],
                'SSCPTEANA' => $post['SSCPTEANA'],
                'CODGES'    => $post['CODGES'],

                'CS' => $csEntete,
                'pj' => $arrayPJ,
                'ligne' => $ligneInsert,
                'confirm' => 'false'
            ];

            $wsdlReturn = $this->_callWsdlModifAndSign($numCde, $signataire, $arraySign);

            if ($wsdlReturn != null) {
                return $wsdlReturn;
            }

            return new Response(200);
        } else {
            return new Response(400, [], (string) json_encode([
                'content' => $this->renderer->render('@popup-erreur/ErreurCreation', [
                    'ErreurValid' => $validator->getError(),
                ]),
            ]));
        }
    }

    //_____________________________________________________________________________
    // Abstract AbsSignatureController

    protected function processSignature(bool $confirm, string $mode, array $listEntityId, string $password = null, string $message = null, string $deleg = null, $post = []) :\SimpleXMLElement
    {
        $signature = new \Modules\Commande\WebService\Commande();
        $signature = $signature->signatureMultiCommande(
            $password,
            $mode,
            $deleg ?? $_SESSION['Session_Login'],
            $listEntityId,
            $confirm,
            $message ?? '',
            $post
        );
        return new \SimpleXMLElement($signature->responseData);
    }

    protected function changementSignataire(string $idDoc, string $password, string $newSig) :\SimpleXMLElement
    {
        $signature = new \Modules\Commande\WebService\Commande();
        $signature = $signature->signatureCommande([
            'MotdePasse' => $password,
            'Mode' => 'M',
            'NumCde' => $idDoc,
            'NvSignataire' => $newSig,
            'Signataire' => $_SESSION['Session_Login'],
            'Confirm' => 'false',
        ]);

        return new \SimpleXMLElement($signature->responseData);
    }

    /**
     * @param array<mixed> $arraySign
     * @return \SimpleXMLElement
     */
    protected function modifEtSigner(string $idDoc, string $signataire = null, $arraySign = []) :\SimpleXMLElement
    {
        $signature = new \Modules\Commande\WebService\Commande();
        $signature = $signature->modifierEtSignature($this->pdo, $idDoc, $signataire, $arraySign, ($arraySign['confirm'] ?? '') == 'true');

        return new \SimpleXMLElement($signature->responseData);
    }

    /**
     * @param string $mode
     * @param string|null $signataire
     * @return string
     */
    protected function getPopupSignaturePath(string $mode, $signataire = '') :string
    {
        return $this->router->generateUri(
            'Signature.SignatureCde.popupSignature',
            array_merge(['mode' => $mode], $signataire? ['signataire'=> $signataire]:[])
        );
    }

    /**
     * @param string $mode
     * @param string|null $signataire
     * @return string
     */
    protected function getConfirmSignaturePath(string $mode, $signataire = '') :string
    {
        return $this->router->generateUri(
            'Signature.SignatureCde.confirmationSignature',
            array_merge(['mode' => $mode], $signataire? ['signataire'=> $signataire]:[])
        );
    }

    /**
     * @param string $mode
     * @param string $signataire
     * @return string
     */
    protected function getAsynchronePath(string $mode, string $signataire = null) :string
    {
        return $this->router->generateUri(
            'Signature.SignatureCde.asynchSignature',
            array_merge(['mode' => $mode], $signataire? ['signataire'=> $signataire]:[])
        );
    }
    
    /**
     * @param string $signataire
     * @return string
     */
    protected function getListePath(string $signataire = null) :string
    {
        return $this->router->generateUri(
            'Signature.SignatureCde.listeDoc',
            $signataire? ['signataire'=> $signataire]:[]
        );
    }
    protected function getChangementSignatairePath(string $idDoc) :string
    {
        return $this->router->generateUri(
            'Signature.SignatureCde.changementSignataire',
            ['idDoc' => $idDoc]
        );
    }

    protected function getXmlTagKey() :string
    {
        return 'Cde';
    }

    protected function getLabelTheEntity() :string
    {
        $trad = $this->getTranslationService();
        return $trad->t('la commande') ;
    }

    protected function getLabelEntity() :string
    {
        $trad = $this->getTranslationService();
        return $trad->t('commande') ;
    }

    protected function getTagHastutil() :string
    {
        return 'SIG_CDE';
    }

    /**
     * _callWsdlModifAndSign
     *
     * @param  string $numCde
     * @param  string $signataire
     * @param  array<mixed> $arraySign
     * @return void|Response
     */
    protected function _callWsdlModifAndSign(string $numCde, string $signataire = null, array $arraySign = [])
    {
        $signOut = $this->modifEtSigner($numCde, $signataire, $arraySign);
            
        if ($signOut->Statut == 'E') {
            return new Response(400, [], (string) json_encode([
                'content' => $this->renderer->render('@popup-erreur/ErreurCreation', [
                    'ErreurValid' => $signOut->MsgErreur,
                ]),
            ]));
        } elseif ($signOut->Statut != 'O') {
            /** on crypter le mot de passe afin de l'envoyer dans les posts  */
            $payload = [
                'user'=> $_SESSION["Session_Login"] ,
                'sessionId'=> session_id(),
                'exp' => time()+30*60*60*60*60,
                'PWD'   => $arraySign['password'],
            ];

            $arraySign['password'] = \Firebase\JWT\JWT::encode((array)$payload, $this->JWTKEY, 'HS256');

            return new Response(400, [], (string) json_encode([
                'content' => $this->renderer->render('@popup-erreur/ErreurXml', [
                    'ErreurValid' => $signOut,
                    'pathValidation' => $this->router->generateUri('Signature.SignatureCde.confirmValidation', ['idDoc' => $numCde, 'signataire' => $signataire]),
                    'post' => json_encode($arraySign)
                ]),
            ]));
        }
    }

    /**
     * @return CdeSignRepository
     */
    protected function getRepository(\PDO $pdo)
    {
        return new CdeSignRepository($pdo);
    }

    protected function refreshSessionCount(\PDO $pdo) : void
    {
        InitSession::initSignCommande($pdo, true);
        InitSession::countDeleg($pdo, true);
    }
}
