<?php
namespace Modules\Commande\Controller;

use Entity\Model\AoEntet;
use Entity\Model\AoLigne;
use Entity\Model\AoRetParLigne;
use Entity\Model\NoReserv;
use Entity\Model\Paramnum;
use Entity\Model\Codecomp;
use Entity\Model\Parametr;
use Entity\Model\Paravrac;
use Entity\Model\Sscptana;
use Modules\Commande\Repository\NotationCommande;
use Modules\GlobalApplication\Repository\LicenceOxalys;
use Modules\TermeDePaiement\Service\TermeDePaiementService;
use Skeleton\Controller\Controller;
use Helpers\Ariane\Ariane;
use Helpers\Trad\Trad;
use Modules\Commande\Repository\CreationCommande;
use Entity\Model\Langues;
use Helpers\Outil\Sql;
use Helpers\Outil\Roles;
use Helpers\Validator\Validator;
use GuzzleHttp\Psr7\Response;
use Modules\Commande\Repository\ValidationCommande;
use Entity\Model\CaEntet;
use Entity\Model\CaEvent;
use Entity\Model\Codgest;
use Entity\Model\Fourniss;
use Entity\Model\Hastutil;
use Entity\Model\Sectimpu;
use Entity\Model\Societe;
use Entity\Model\TacFyfo;
use Helpers\ChampsSupplementaire\ChampSupp;
use Helpers\Outil\Date;
use Modules\Commande\Repository\CommandeEventRepo;
use Modules\Commande\Service\CreationCommandeService;
use Modules\GlobalApplication\Repository\Numerotation;
use Traits\Validator\Zoom;

class CreationCommandeController extends AbsModificationCommandeController
{
    public function creationAction() : string
    {

        $post    = $this->request->getParsedBody();
        $typeCde = $this->request->getAttribute('typeCde');
        $numType = $this->request->getAttribute('numType');
        $modele = [];

        $postExist = false;
        if ($post) {
            $postExist = true;
        }
        
        $creationCdeRepo = new CreationCommande($this->pdo);
        $param = [];

        $infoUser = $creationCdeRepo->ModeleUser();

        $modeleActive = $creationCdeRepo->modeleDesactiver()['MODELE_DESACTIVE'];
        /* MODELE_DESACTIVE different de P active le champs modele de commande */
        if ($modeleActive!='P') {
            $param['MODELE_ACTIF'] = true;
            /* si le modele de l'utilisateur est obligatoire, on vérouille la saisie du champs modele de commande */
            $param['OBLI_MODELE'] = Sql::toBool($infoUser['MOD_OBLI']) || $modeleActive=='O';

            /* on récupere les parametrages du modele de l'utilisateur */
            if ($post['modeleCde'] ?? '' != '') {
                $modele = $creationCdeRepo->getModele($post['modeleCde']);
            } elseif ($infoUser['MOD_DEF']) {
                $modele = $creationCdeRepo->getModele($infoUser['MOD_DEF']);
            }
        }
        /* ******* */
        $param['expeditionActif'] = (new LicenceOxalys($this->pdo))->expeditionActive();

        $qbParavrac = new Paravrac($this->pdo);
        
        /* affichage type marché public */
        $param['AFF_TMP'] = $qbParavrac->getGeneric('CTRLSEUILPARSFA')=='O';

        /* affichage type marché du fournisseur */
        $param['TYPEACHAT_ACTIF'] = $qbParavrac->getValue('PARAMFOU', 'INITTAC') ? true:false;

        /* affichage des langue fournisseur */
        $param['LANGUE_ACTIF'] = $qbParavrac->getValue('PARAMOXA', 'MULTILNGACTIF')=='O';

        /* reception automatique modifiable ? */
        $param['LOCK_SAISIEREC'] =
            Roles::droitsUtilisateur($this->pdo, 'HA_CA_MOFR')!='1'
            && $qbParavrac->getGeneric('CDERECEPTNONMODIF') == 'O';
        
        $INVISIBLE_SUR_CA_SI_CDC_SCA = sql::paravrac($this->pdo, 'PARAMGEN', 'INVISIBLE_SUR_CA_SI_CDC_SCA');

        $param['SI_ACTIF']          = substr($INVISIBLE_SUR_CA_SI_CDC_SCA, 0, 1)!='O'? true:false;
        $param['CDC_ACTIF']         = substr($INVISIBLE_SUR_CA_SI_CDC_SCA, 2, 1)!='O'? true:false;
        $param['SCA_ACTIF']         = substr($INVISIBLE_SUR_CA_SI_CDC_SCA, 4, 1)!='O'? true:false;

        $param['SI_SECTO'] = \Helpers\Outil\Roles::droit($this->pdo, 'SISECTOR', 'PARAMSTE');
        $param['CDC_SECTO'] = \Helpers\Outil\Roles::droit($this->pdo, 'CDCSECTO', 'PARAMSTE');
        $param['SCA_SECTO'] = \Helpers\Outil\Roles::droit($this->pdo, 'SCASECTO', 'PARAMSTE');

        /* Initialisation a l'arrivé sur l'écran */
        if (!$post) {
            $post['DATE_PER'] = Date::dateConverte(date('Ymd'));
            
            /* on verifie que l'utilisateur connecté est bien acheteur */
            if (Sql::boolSql($infoUser['ACHETEUR'])) {
                $post['ACH'] = $_SESSION['Session_Login'];
            }
            
            /* initialisation par modèle */
            if (count($modele)) {
                $post['modeleCde']  = $infoUser['MOD_DEF'];
                $post['CTR_EMETT']  = $modele['CTR_E'];
                $post['CTR_LIV']    = $modele['CTR_L'];
                $post['SECTIMP']    = $modele['SI'];
                $post['CODECOMP']   = $modele['CDC'];
                $post['SSCPTEANA']  = $modele['SCA'];
                $post['CODE_FOU']   = $modele['FOU'];
                $post['SAISIEREC']  = Sql::boolSql($modele['RECEP']);
            }
            
            /* societe du modele, ou la societe user connecté */
            $post['CODE_STE']    = $modele['SOC']??$_SESSION['Session_SocUsr'];

            /* type cde du modele ou le type cde par defaut */
            $post['TYPEDOC']    = $modele['TYP'] ?? $qbParavrac->getGeneric('TYP_DOC_DEF');

            /* type de marche public */
            $post['TYPNMP']     = $modele['TYPNMP'] ?? $qbParavrac->getValue('CTRLSESFA', 'TYPACHDEF');
            
            $post['SAISIEREC']  = ($qbParavrac->getGeneric('CDERECEPT')=='O');

            $post['CTR_EMETT']    = $_SESSION['Session_CodeCtrEmetteur'];
            $post['CTR_LIV']      = $_SESSION['Session_CodeCtrLivraison'];

            /* ******************* */
        } else {
            $post['TYPEDOC'] = $post['TYP_DOC'];
        }
        
        /* ********************************* */
        /* si l'utilisateur select un MODELE */
        /* ********************************* */
        
        $fournisseur = false;

        if (isset($post['MODE']) && $post['MODE']=='ChangeMODELE') {
            $modele = $creationCdeRepo->getModele($post['modeleCde']??'');
            
            $post['CODE_STE']   = $modele['SOC']?: $post['CODE_STE'];
            $post['TYPEDOC']    = $modele['TYP']?: $post['TYPEDOC'];
            $post['TYNMP']      = $modele['TYNMP']?: $post['TYNMP'];
            $post['CTR_EMETT']  = $modele['CTR_E']?: $post['CTR_EMETT'];
            $post['CTR_LIV']    = $modele['CTR_L']?: $post['CTR_LIV'];
            $post['SECTIMP']    = $modele['SI']?: $post['SECTIMP'];
            $post['CODECOMP']   = $modele['CDC']?: $post['CODECOMP'];
            $post['SSCPTEANA']  = $modele['SCA']?: $post['SSCPTEANA'];
            $post['CODE_FOU']   = $modele['FOU']?: $post['CODE_FOU'];
            $post['SAISIEREC']  = $modele['SAISIEREC']? Sql::boolSql($modele['RECEP']):sql::boolSql($post['SAISIEREC']);

            $fournisseur = true;
        }

        /* Si on a un modèle, alors on récupère le parametrage, il peut venir du POST ou du parametrage du user */
        if (count($modele)) {
            $param['LOCK_SOC']       = Sql::boolSql($modele['SOCVER']);
            $param['LOCK_TYP']       = Sql::boolSql($modele['TYPVER']);
            $param['LOCK_TYPNMP']    = Sql::boolSql($modele['TYNMPVER']);
            $param['LOCK_CTR_EMET']  = Sql::BoolSql($modele['CTR_EVER']);
            $param['LOCK_CTR_LIV']   = Sql::BoolSql($modele['CTR_LVER']);
            $param['LOCK_SI']        = Sql::BoolSql($modele['SIVER']);
            $param['LOCK_CDC']       = Sql::BoolSql($modele['CDCVER']);
            $param['LOCK_SCA']       = Sql::BoolSql($modele['SCAVER']);
            $param['LOCK_FOU']       = Sql::BoolSql($modele['FOUVER']);
            $param['LOCK_SAISIEREC'] =
                Roles::droitsUtilisateur($this->pdo, 'HA_CA_MOFR')!='1'
                && (
                    Sql::toBool($modele['RECEPVER'])
                    || $qbParavrac->getGeneric('CDERECEPTNONMODIF') == 'O'
                );
        }

        /* ****************************** */
        /* si l'utilisateur select une DA */
        /* ou si on viens d'une DA        */
        /* ****************************** */
        if (($post['MODE'] ?? null) == 'ChangeDA' || (!$postExist && $typeCde=='DA')) {
            $post['origineCde'] = 'DA';
            $post['DA']= $post['DA']??$numType;
            
            $codeDA             = $creationCdeRepo->getDA($post['DA']);
            
            if ($typeCde=='DA') {
                $post['CODE_STE'] = $codeDA['CODE_STE'];
                $param['LOCK_SOC'] = true;
                $param['LOCK_DA'] = true;
            }
            
            $post['DEMANDEUR']  = $codeDA['NO_DEM'];

            if (!$modele || Sql::toBool($modele['CTR_EVER']) || !$modele['CTR_E']) {
                $post['CTR_EMETT']  = $codeDA['DAENT_CENTRE_EMETTEUR'];
            }

            if (!$modele || Sql::toBool($modele['CTR_LVER']) || !$modele['CTR_L']) {
                $post['CTR_LIV']    = $codeDA['CTR_LIV'];
            }

            if (!$modele || Sql::toBool($modele['TYPVER']) || !$modele['TYP']) {
                $post['TYPEDOC']  = $codeDA['TYP_DOC'];
            }

            $post['MOD_TRANS']  = $codeDA['MOD_TRS'];

            if (!$modele || Sql::toBool($modele['SIVER']) || !$modele['SI']) {
                $post['SECTIMP']    = $codeDA['SECTIMP'];

                $cgParId = \Helpers\Outil\Roles::droit($this->pdo, 'CODE_GESTION_PAR_ID');
                if ($cgParId) {
                    $post['CODGES']     = $codeDA['ID_CG'];
                } else {
                    $post['CODGES']     = $codeDA['CODGES'];
                }
            }

            if (!$modele || Sql::toBool($modele['CDCVER']) || !$modele['CDC']) {
                $post['CODECOMP']   = $codeDA['CODECOMP'];
            }

            if (!$modele || Sql::toBool($modele['SCAVER']) || !$modele['SCA']) {
                $post['SSCPTEANA']  = $codeDA['SSCPTEANA'];
            }

            if (!$modele || !Sql::toBool($modele['FOUVER']) || !$modele['FOU']) {
                $post['CODE_FOU']   = $codeDA['FOU'];
            }

            $devise = $codeDA['DEVISE'];
            

            //todo saisie recep / recep auto

            $fournisseur    = true;
            
            $numElement     = $post['DA'];
            $typeElement    = 'DA';

            $titre                  = $creationCdeRepo->getTitreDA($numElement)['CONTMEMO'];
            $listeLigne             = $creationCdeRepo->getLigneDA($numElement);
            $listeClause            = $creationCdeRepo->getClauseDA($numElement);
            $listePJ                = $creationCdeRepo->getJPDA($numElement);
            $daHasTp                = $creationCdeRepo->getNumberTP($numElement);
            $DAHasLignesTraitees     = $creationCdeRepo->getCountDaLigneTraitee($numElement);
        }
        
        /* ***************************** */
        /* si l'utilisateur select un AO */
        /* ou si on viens d'une AO       */
        /* ***************************** */
        if ((isset($post['MODE']) && $post['MODE']=='ChangeAO') || (!$postExist && $typeCde=='AO')) {
            $post['origineCde'] = 'AO';
            $post['AO']         = $post['AO']??$numType;
            //$codeAO             = $creationCdeRepo->getDA($post['AO']);
            
            
            if ($typeCde=='AO') {
                $ao = $creationCdeRepo->getEnteteAo($post['AO']);
                $param['LOCK_AO'] = true;
                if ($ao['TYPE_SG']=='S') {
                    $post['CODE_STE']  = $ao['CODE_STE'];
                    $param['LOCK_SOC'] = true;
                } else {
                    /*
                     * Si type_sg = G, alors on récupere toute les societe du groupe de societe $ao['CODE_STE']
                     * on envoie filter_soc en param a la vue pour ajouter le filtre sur les groupe
                     */
                    $param['filter_SOC'] = "filter_egal_GROUPE : '".$ao['CODE_STE']."'";
                }
            }
            
            $post['CODE_FOU'] = '';
            $post['COD_TAC'] = '';
            
            $post['DEMANDEUR']  = $creationCdeRepo->getElementAO('NO_DEM', $post['AO'])['VALUE'];

            if (!$modele || Sql::toBool($modele['CTR_EVER'])) {
                $post['CTR_EMETT']  = $creationCdeRepo->getElementAO('DAENT_CENTRE_EMETTEUR', $post['AO'])['VALUE'];
            }

            if (!$modele || Sql::toBool($modele['CTR_LVER'])) {
                $post['CTR_LIV']    = $creationCdeRepo->getElementAO('CTR_LIV', $post['AO'])['VALUE'];
            }

            if (!$modele || Sql::toBool($modele['SIVER'])) {
                $cgParId = \Helpers\Outil\Roles::droit($this->pdo, 'CODE_GESTION_PAR_ID');
                if ($cgParId) {
                    $field     = 'ID_CG';
                } else {
                    $field     = 'CODGES';
                }
                $post['SECTIMP']    = $creationCdeRepo->getElementAO('SECTIMP', $post['AO'])['VALUE'];
                $post['CODGES']     = $creationCdeRepo->getElementAO($field, $post['AO'])['VALUE'];
            }

            if (!$modele || Sql::toBool($modele['CDCVER'])) {
                $post['CODECOMP']   = $creationCdeRepo->getElementAO('CODECOMP', $post['AO'])['VALUE'];
            }

            if (!$modele || Sql::toBool($modele['SCAVER'])) {
                $post['SSCPTEANA']  = $creationCdeRepo->getElementAO('SSCPTEANA', $post['AO'])['VALUE'];
            }
            
            $devise     = $creationCdeRepo->getElementAO('DEVISE', $post['AO'])['VALUE'];
            
            //$fournisseur    = true;
            
            $numElement     = $post['AO'];
            $typeElement    = 'AO';
            
            $titre          = $creationCdeRepo->getTitreAO($numElement)['CONTMEMO'];
            $listeLigne     = $creationCdeRepo->getLigneAO($numElement, $post['CODE_STE']);
            $listeClause    = $creationCdeRepo->getClauseAO($numElement);
            $listePJ        = $creationCdeRepo->getJPAO($numElement);
        }
        
        /* *********************************** */
        /* si l'utilisateur change fournisseur */
        /* ou si on viens d'une DA             */
        /* *********************************** */

        if (($post['CODE_FOU']??'') != '') {
        } elseif (($post['text_CODE_FOU']??'') != '') { // TODO : why ?
            $post['CODE_FOU'] = $post['text_CODE_FOU'];
        }

        if (($post['MODE'] ?? null)=='ChangeFournisseur' || ($fournisseur && $post['CODE_FOU'] != '')) {
            $infoFournisseur = $creationCdeRepo->getInfoFournisseur($post['CODE_FOU']);

            // TODO:  what happen if $infoFournisseur is empty (CODE_FOU is invalid) ?

            $post['confirmationAchat'] = false;

            Date::dateToSql($post['DATEDEBCONT']);
            Date::dateToSql($post['DATEFINCONT']);
            
            $tycTacfou = new TacFyfo($this->pdo);
            $typeAchatDef = $tycTacfou->find(['TACFOFOU' => $post['CODE_FOU'], 'TACFODEF' => 'T']);
            $listeTypeAchat = $tycTacfou->findAll(['TACFOFOU' => $post['CODE_FOU']]);

            if ($typeAchatDef) {
                $typeAchat = $typeAchatDef['TACFOTAC'];

                if (count($listeTypeAchat) == 1) {
                    $post['confirmationAchat'] = true;
                    $param['LOCK_confirmationAchat'] = true;
                }
            } else {
                $typeAchat = $qbParavrac->getValue('PARAMFOU', 'INITTAC');
                $post['confirmationAchat'] = true;
                $param['LOCK_confirmationAchat'] = true;
            }
            
            $post['DEVISE'] = $devise??$infoFournisseur['DEVISE'];

            if ($infoFournisseur['COD_LNG']) {
                $post['COD_LNG'] = $infoFournisseur['COD_LNG'];
            } else {
                $user = new Hastutil($this->pdo);
                $post['COD_LNG'] = $user->find($_SESSION["Session_Login"])['COD_LNG']??'';
            }
            $post['COD_TAC'] = $typeAchat;

            $modTransActif = $creationCdeRepo->modeTransportActif($post['CTR_LIV']);
            if (!Sql::toBool($modTransActif['TRS_INTER'])) {
                $post['SAISIEREC'] = Sql::boolSql($post['SAISIEREC']);

                if (!$param['LOCK_SAISIEREC'] && $post['SAISIEREC']) {
                    $post['RECEP_AUTO']         = Sql::boolSql($infoFournisseur['RECEP_AUTO']);

                    if ($post['RECEP_AUTO']) {
                        $post['CONTRAT_PERIOD']     = $infoFournisseur['PER_REC_AUTO'];
                    }
                }
            }
        }
        
        /* on fait le controle sur la section d'imputation voir si elle a des Code gestion actif */
        if ($post['SECTIMP']??'') {
            $codeGestActif = $creationCdeRepo->codeGestionActif($post['SECTIMP'], $post['CODE_STE']??null)['SICODG']??'';
            if (Sql::toBool($codeGestActif)) {
                $param['MODIF_CODGES'] = true;
            }
        }
        
        /* controle afin de voir si le chps Mode transport est actif et mettre un mode de transport par defaut si il n'éxiste pas */
        if ($post['CTR_LIV']??'') {
            $modTransActif = $creationCdeRepo->modeTransportActif($post['CTR_LIV']);
            if (Sql::toBool($modTransActif['TRS_INTER'])) {
                $param['MODIF_MODTRANS']=true;
                $post['MOD_TRANS'] = $modTransActif['MOD_TRS'];
            }
        }

        /************ PARAMETRAGE VUE *****************/

        $trad = $this->getTranslationService();
        
        $langues = array_column(
            (new Langues($this->pdo))->fetchAll(),
            'LIBELLE',
            'COD_LNG'
        );

        $listeTransport = $creationCdeRepo->getAllModeTransportTrad();
        $transport = array_column($listeTransport, 'MOD_TRS_TRAD', 'MOD_TRS');

        for ($i=0; $i<32; $i++) {
            $tabJoursAppli[$i]=$i;
        }

        Ariane::generate(1, $trad->t('Nouvelle commande'));

        $paramNum = (new Paramnum($this->pdo))->getNodeNum('CA', $post['CODE_STE']);
        
        $post['SAISIEREC'] = Sql::boolSql($post['SAISIEREC']??false);
        $post['RECEP_AUTO'] = Sql::boolSql($post['RECEP_AUTO']??false);

        return $this->renderer->render('@Commande/Creation/entete', [
            'typeCde' => $typeCde,
            'tabJoursAppli'         => $tabJoursAppli,
            'tabTransport'          => $transport,
            'tabLangues'            => $langues,
            'param'                 => $param,
            'cde'                   => $post,
            
            'listeClause'           => $listeClause??[],
            'typeElement'           => $typeElement??'',
            'listeLigne'            => $listeLigne??[],
            'numElement'            => $numElement??'',
            'daHasTp'               => $daHasTp??0,
            'listePJ'               => $listePJ??[],
            'titre'                 => $titre??'',
            'MODE'                  => 'Creation',
            'paramNum'              => $paramNum,
            'commandeConfig' => (new Parametr($this->pdo))->getCommandeUpdateConfig(),
            'impConfig' => (new Paravrac($this->pdo))->getCommandeAxeImpConfig(),
            'DAHasLignesTraitees'   => $DAHasLignesTraitees ?? false
        ]);
    }
    
    //TODO si on viens d'une DA ou AO géré le CODE SOCIETE !!!!
    public function validationAction() :Response
    {
        $post = $this->request->getParsedBody();
        $mode = $this->request->getAttribute('mode');
        $trad = $this->getTranslationService();
                
        $validator = $this->createValidator();
        $creationRepo = new CreationCommande($this->pdo);
        $requete = new ValidationCommande($this->pdo);

        /***************/
        /** Validator **/

        $infoUser = $creationRepo->ModeleUser();
        $modeleActive = $creationRepo->modeleDesactiver()['MODELE_DESACTIVE'];

        if ($modeleActive!='P') {
            if (Sql::toBool($infoUser['MOD_OBLI']) || $modeleActive == 'O') {
                $validator->zoom('Mca', $post['modeleCde'], $trad->t('modèle'), $this->pdo, false);
            }
        }

        $validator->societeZoom($post['CODE_STE'], $trad->t('Société'), $this->pdo, false);
        $validator->zoom('Hastutil', $post['ACH'], $trad->t('Acheteur'), $this->pdo, false, ['filter_ACHETEUR' =>  'T']);
        
        $modeNumerotation = (new Paramnum($this->pdo))->getNodeNum('CA', $post['CODE_STE']);
        /* Commande */
        $validator->isInteger(
            $trad->t('Numéro commande'),
            $post['NO_CDE'],
            $modeNumerotation=='M' ?
                1 : 0,
            9
        );
        $validator->entityAlreadyExist(
            $trad->t('Le numéro de commande saisi existe déjà.'),
            new CaEntet($this->pdo),
            $post['NO_CDE'],
            []
        );

        if (($modeNumerotation=='M' || $modeNumerotation=='I') && $post['NO_CDE']) {
            $validator->entityAlreadyExist(
                $trad->t('Le numéro de commande saisi existe déjà.'),
                new NoReserv($this->pdo),
                ['NO_CA' => $post['NO_CDE']],
                []
            );
        }



        $validator->zoom('typeDoc', $post['TYP_DOC'], $trad->t('type de commande'), $this->pdo);
        
        $validator->isDateOuverte($trad->t('Date période'), $post['DATE_PER'], $post['CODE_STE'], 'CDE', false);
        /********************/
        /** Initialisation **/
        $nmTitre = '';
        /* Si une DA est selectionné, on vérifie qu'elle est remplie et que code correspond */
        if ($post['origineCde']=='DA') {
            if ($post['DA']) {
                $post['codeSte']= $post['CODE_STE'];
                $DA = $requete->listeDaPourCde($post['DA'], $post);
                $validator->isFalse($DA, Trad::strBuild($trad->t('Le code saisi @1@ n\'est pas présent dans la liste des DA.'), $post['DA']));
                
                $nmTitre = Sql::getMemo($this->pdo, ($DA['NM_TITRE']??''));
            } else {
                $validator->setError($trad->t('Le champ DA ne peut pas être vide.'));
            }
        } elseif ($post['origineCde']=='AO') {
            /* Sinon une AO est selectionné, on vérifie qu'elle est remplie et que code correspond */
            if ($post['AO']) {
                $post['codeSte']= $post['CODE_STE'];
                $AO = $requete->listeAoPourCde($post['AO'], $post);
                $validator->isFalse($AO, Trad::strBuild($trad->t('Le code saisi @1@ n\'est pas présent dans la liste des consultations de la société.'), $post['AO']));
                
                $nmTitre = Sql::getMemo($this->pdo, $AO['NM_TITRE']);
            } else {
                $validator->setError($trad->t('Le champ AO ne peut pas être vide.'));
            }
        }

        $validator->isCheck($post['Titre']);

        $aoLigneRepartition = new AoRetParLigne($this->pdo);
        $aoLigneEntity = new AoLigne($this->pdo);
        $aoEntet = new AoEntet($this->pdo);
        $listeLigne =[];
        $listeClause = [];
        $listePJ = [];

        
        $validator->zoom(
            'Fourniss',
            $post['CODE_FOU'],
            'Fournisseur',
            $this->pdo
        );
        
        $fournissEntity = new Fourniss($this->pdo);
        $fourniss = $fournissEntity->find($post['CODE_FOU']);
        
        foreach ($post as $key => $val) {
            $explodeKey = explode('_', $key);
            if (strpos($key, 'ligne_') === 0) {
                $listeLigne[] = [
                    'origine'   => $post['origineCde'],
                    'id'        => $post[$post['origineCde']],
                    'noPo'      => $explodeKey[1],
                ];

                if ($post['origineCde'] == 'AO') {
                    $fourLigneAo = $aoLigneRepartition->find(['NO_AO' => $post[$post['origineCde']], 'NO_PO' => $explodeKey[1]]);
                    $aoLigne = $aoLigneEntity->find(['NO_AO' => $post[$post['origineCde']], 'NO_PO' => $explodeKey[1]]);

                    if ($fourLigneAo['CODE_FOU'] != $post['CODE_FOU'] && $post['CODE_FOU']) {
                        $validator->setError(
                            Trad::strBuild(
                                $trad->t('Le fournisseur @1@ (@2@) n\'a pas été retenu pour la ligne @3@ de la consultation @4@.'),
                                ($fourniss['RS'] ?? ''),
                                $post['CODE_FOU'],
                                $explodeKey[1],
                                $post[$post['origineCde']]
                            )
                        );
                    }

                    if ($aoLigne['CODE_STE'] != $post['CODE_STE'] && $post['CODE_STE']) {
                        $socTmp = new Societe($this->pdo);
                        $soc = $socTmp->find($aoLigne['CODE_STE']);
                        $validator->setError(trad::strBuild($trad->t('La société @1@ (@2@) de la ligne @3@ de la consultation est différente de la commande.'), $soc['RAIS_SOC'], $post['CODE_STE'], $explodeKey[1]));
                    }
                }
            } elseif (strpos($key, 'clause_') === 0) {
                $listeClause[] = [
                    'origine'   => $post['origineCde'],
                    'id'        => $post[$post['origineCde']],
                    'noClause'  => $explodeKey[1],
                ];
            } elseif (strpos($key, 'pj_') === 0) {
                $listePJ[] = [
                    'origine'   => $post['origineCde'],
                    'id'        => $post[$post['origineCde']],
                    'noPJ'      => $explodeKey[1],
                ];
            }
        }
        
        $validator->zoom(
            'Hastutil',
            $post['DEMANDEUR'],
            $trad->t('demandeur'),
            $this->pdo,
            true,
            ['filter_DEMAND' => 'T',/* 'filter_CODE_STE' => $post['CODE_STE']*/]
        );
        $validator->zoom('Centre', $post['CTR_EMETT'], $trad->t('centres émetteurs'), $this->pdo, false, ['filter_EMISSION' =>  'T', 'filter_CODE_STE' => $post['CODE_STE']]);
        $validator->zoom('Centre', $post['CTR_LIV'], $trad->t('centres de livraison'), $this->pdo, false, ['filter_LIVRAISON' =>  'T', 'filter_CODE_STE' => $post['CODE_STE']]);
        
        
        $modTransActif = $creationRepo->modeTransportActif($post['CTR_LIV']);
        
        if (!$modTransActif || !Sql::toBool($modTransActif['TRS_INTER'])) {
            unset($post['MOD_TRANS']);
        }

        $paramtr = (new Parametr($this->pdo));

        /* SI CG CD SCA */
        $config = (new Paravrac($this->pdo))->getCommandeAxeImpConfig($post['CODE_STE']);
        
        if ($config->SectImp->isActive) {
            $cgParId = Roles::droit($this->pdo, 'CODE_GESTION_PAR_ID')? 1:0;
            
            $validator->zoom(
                'Sectimpu',
                $post['SECTIMP'],
                $trad->t('sections d\'imputation'),
                $this->pdo,
                true,
                $config->SectImp->isSecto ?
                    ['filter_CODE_STE' => $post['CODE_STE']] : []
            );
            
            $sectionImp = (new Sectimpu($this->pdo))->find(
                ['CODE_SI' => $post['SECTIMP']]+($config->SectImp->isSecto ?['CODE_STE' => $post['CODE_STE']] : [])
            );


            if ($sectionImp != null) {
                $sectionImp['SICODG'] = Sql::toBool($sectionImp['SICODG']);
                $sectionImp['IMPCODG'] = Sql::toBool($sectionImp['IMPCODG']);

                // Validate SectImpu date
                $validator->entityDateValidation(
                    CaEntet::class,
                    Sectimpu::class,
                    $trad,
                    $sectionImp['DATE_DEB'],
                    $sectionImp['DATE_FIN'],
                    $post['DATE_PER']
                );
            }


            if (isset($sectionImp) && ($sectionImp['SICODG']??false)) {
                // TODO prendre en compte le paramétrage CODE_GESTION_PAR_ID
                $validator->codeGestionZoom(
                    $post['CODGES'],
                    $trad->t('code gestion'),
                    $this->pdo,
                    ! $sectionImp['IMPCODG'],
                    [
                        'CODE_SI' => $post['SECTIMP'],
                        'cgParId' => $cgParId
                    ]
                );
                
                $infoCg = (new Codgest($this->pdo))->find([
                    'CODE_STE' => $sectionImp['CODE_STE'],
                    'CODE_SI' => $post['SECTIMP'],
                ] + ($cgParId ? [
                    'CODE_GES' => $post['CODGES']
                ] : [
                    'CODE_AFF' => $post['CODGES']
                ]));
                
                if ($infoCg != null) {
                    // Validate CodeGest
                    $validator->entityDateValidation(
                        CaEntet::class,
                        Codgest::class,
                        $trad,
                        $infoCg['DTEVALMIN'],
                        $infoCg['DTEVALMAX'],
                        $post['DATE_PER']
                    );
                }
            }
        }
        if ($config->CodeCompl->isActive) {
            $validator->zoom(
                'Codecomp',
                $post['CODECOMP'],
                $trad->t('codes complémentaires'),
                $this->pdo,
                true,
                $config->CodeCompl->isSecto ?
                    ['filter_egal_CODE_STE' => $post['CODE_STE']] : []
            );

            $codeComp = (new Codecomp($this->pdo))->find(
                ['CODE_CDC' => $post['CODECOMP']]+($config->CodeCompl->isSecto ?['CODE_STE' => $post['CODE_STE']] : [])
            );

            if ($codeComp != null) {
                $validator->entityDateValidation(
                    CaEntet::class,
                    Codecomp::class,
                    $trad,
                    $codeComp['DATE_DEB'],
                    $codeComp['DATE_FIN'],
                    $post['DATE_PER']
                );
            }
        }
        if ($config->SousCompteAna->isActive) {
            $validator->zoom(
                'Sscptana',
                $post['SSCPTEANA'],
                $trad->t('sous-comptes d\'analyse'),
                $this->pdo,
                true,
                $config->SousCompteAna->isSecto ?
                    [
                        /*'filter_egal_CODE_CTA' => 'CA',*/
                        'filter_egal_CODE_STE' => $post['CODE_STE']
                    ] : []
            );

            $sousComptAna = (new Sscptana($this->pdo))->find(
                ['CODE_SCA' => $post['SSCPTEANA']]+($config->SousCompteAna->isSecto ?['CODE_STE' => $post['CODE_STE']] : [])
            );

            if ($sousComptAna != null) {
                $validator->entityDateValidation(
                    CaEntet::class,
                    Sscptana::class,
                    $trad,
                    $sousComptAna['DATE_MINI'],
                    $sousComptAna['DATE_MAXI'],
                    $post['DATE_PER']
                );
            }
        }
        
        $validator->isDate($post['DTE_LIV'], '', '', true, $trad->t('date de livraison'));

        /*****************/
        /** Fournisseur **/
        if ($post['origineCde']=='AO') {
            if ($post['CODE_FOU']) {
                $isFourAo = $creationRepo->fournisseurParAo(['filter_NO_AO' => $post['AO'], 'filter_CODE' => $post['CODE_FOU']]);
                $validator->isFalse($isFourAo, Trad::strBuild($trad->t('Le code saisi @1@ n\'est pas présent dans la liste des fournisseurs pour cette consultation.'), $post['CODE_FOU']));
            } else {
                $validator->setError($trad->t('Le champ Fournisseur ne peut pas être vide.'));
            }
        } else {
            $validator->zoom('Fourniss', $post['CODE_FOU'], $trad->t('Fournisseur'), $this->pdo, false, ['filter_PROSPECT' => 'F']);
        }
        
        $validator->zoom('Devise', $post['DEVISE'], $trad->t('Devise'), $this->pdo);
        
        if ($post['CODE_FOU']) {
            $validator->zoom('TypeAchat', $post['COD_TAC'], $trad->t('type d\'achat'), $this->pdo, true);
            if (Sql::paravrac($this->pdo, 'PARAMFOU', 'INITTAC') && $post['COD_TAC']) {
                $validator->isCheck($post['confirmationAchat']);
                $validator->isFalse($post['confirmationAchat'], $trad->t('Le type d\'achat doit être confirmé avant validation.'));
            }
        }
        /***************/
        /** Récéption **/
        $validator->isCheck($post['SAISIEREC']);
        
        /* si saise des répécetion est coché */
        if ($post['SAISIEREC']) {
            $validator->isCheck($post['RECEP_AUTO']);
            
            /* si récéption auto est coché */
            if ($post['RECEP_AUTO']) {
                $validator->isDate($post['DATEDEBCONT'], '', '', false, $trad->t('Début contrat'));
                $validator->isDate($post['DATEFINCONT'], '', '', false, $trad->t('Début fin'));
                if ($post['DATEDEBCONT'] && $post['DATEFINCONT'] && ($post['DATEDEBCONT']>$post['DATEFINCONT'])) {
                    $validator->setError($trad->t('La date de fin ne peut être inférieure à la date de début.'));
                }
            }
        }

        if ($creationRepo->getNumberTP($post['DA']) > 0 && Sql::boolSql($post['allLigne'])) {
            if ($creationRepo->getCountDaLigneTraitee($post['DA'])) {
                $validator->setErrorNonBloquant($trad->t('Les termes de paiement de la demande d’achat ne peuvent pas être repris.'));
            } elseif (!$creationRepo->areTPComplete($post['DA'])) {
                $validator->setErrorNonBloquant($trad->t('Les termes de paiement pour la Demande d\'Achat sont incomplets, ils ne seront pas repris.'));
            }
        }
        
        if ($validator->isNonBloquant() && !isset($post['confirm'])) {
            return $this->createJsonResponse(
                [
                    'type' => 'confirm',
                    'popupHtml' => $this->renderer->render('@popup-erreur/simpleWarning', [
                        'content' => $validator->getErrorNonBloquant(),
                    ]),
                ],
                400
            );
        }
        if (!$validator->isValid(true)) {
            return new Response(400, [], $validator->getError());
        }
        
        //_____________________________
        // Update DB

        if ($mode=='Creation') {
            $creationLigneCommande = new CreationCommandeService($this->pdo, $this->pdoOxaFT, $this->getTranslationService());

            $listeDA = [];
            if ($post['origineCde']=='DA') {
                $listeDA[$post['DA']] = $post['DA'];
            } elseif ($post['origineCde']=='AO') {
                $aoLigne = new AoLigne($this->pdo);
                $ligne = $aoLigne->fetchAll([], ['filter_NO_AO' => $post['AO']]);

                foreach ($ligne as $line) {
                    $listeDA[$line['NO_DA']] = $line['NO_DA'];
                }

                $infoEntet = $aoEntet->find($post['AO'], ['OBJET_AO']);
                $post['OBJET_CA'] = $infoEntet['OBJET_AO'];
            }

            $post['CODE_GES'] = $infoCg['CODE_GES']??'';
            $post['CODE_AFF'] = $infoCg['CODE_AFF']??'';
            $post['LIB_GES'] = $infoCg['LIB_GES']??'';

            $entete = $creationLigneCommande->creationEnteteCde(
                $post,
                $nmTitre,
                $listeDA,
                $post['origineCde'] == 'AO'
            );

            $caEntet = new CaEntet($this->pdo);
            $caEntet->insert($entete);

            $cs = new ChampSupp($this->pdo);

            if ($post['origineCde']=='DA') {
                $cs->copyDefault('CA_ENTET', $entete['NO_CDE'], 'DA_ENTET', $post['DA']);
                if ($creationRepo->getNumberTP($post['DA']) > 0 && Sql::boolSql($post['allLigne']) && !$creationRepo->getCountDaLigneTraitee($post['DA'])) {
                    (new TermeDePaiementService($this->pdo, $trad))->createDuplicateForCDE($post['DA'], $entete['NO_CDE']);
                }
            } elseif ($post['origineCde']=='AO') {
                $cs->copyDefault('CA_ENTET', $entete['NO_CDE'], 'AO_ENTET', $post['AO']);
            }
            
            $cs->copyDefault('CA_ENTET', $entete['NO_CDE'], 'CENTRE', $post['CTR_LIV']);

            $cs->copyDefault('CA_ENTET', $entete['NO_CDE'], 'FOURNISS', $post['CODE_FOU']);
            $cs->copyDefault('CA_ENTET', $entete['NO_CDE'], 'HASTUTIL', $post['DEMANDEUR']);
            $cs->copyDefault('CA_ENTET', $entete['NO_CDE'], 'SOCIETE', $post['CODE_STE']);
            $cs->copyDefault('CA_ENTET', $entete['NO_CDE'], 'TYPDOC', $post['TYP_DOC']);
            
            $creationLigneCommande->createLigneDaAo('', $entete, $listeLigne);
            $creationLigneCommande->createClauseDaAo($entete, $listeClause);
            $creationLigneCommande->createPJDaAo($entete, $listePJ);
            $creationLigneCommande->campagne($entete, $listeDA);
            
            $creationLigneCommande->expedition($entete);

            $suiviCommandeRepo = new CommandeEventRepo($this->pdo);
            $suiviCommandeRepo->insertEvent([
                'NO_CDE'    => $entete['NO_CDE'],
                'CODE'      => 'CRE',
                'TYP_EVE'   => 'I',
            ]);

            Numerotation::deleteReserver($this->pdo, 'CA', $entete['NO_CDE']);

            //_____________________________
            // Post processes

            if ((new LicenceOxalys($this->pdo))->noteFourActive()) {
                // Init notation
                (new NotationCommande($this->pdo))->onCdeCreationInit($entete + [
                    'Fournisseur' => (new Fourniss($this->pdo))->find($entete['CODE_FOU'])
                ]);
            }
        }
        
        $path = $this->router->generateUri(
            'Commande.ModificationCommande.index',
            ['idCommande' => $entete['NO_CDE'] ?? '0']
        );
        
        return $this->createJsonResponse([
            'statut' => 'O',
            'path' => $path??'',
        ]);
    }
}
