<?php

namespace Modules\Commande\Service;

use Entity\Model\Devise;
use Entity\Model\Fourniss;
use Entity\Model\Hastutil;
use Entity\Model\TacFyfo;
use Helpers\Fichier\Fichier;
use Helpers\Outil\Sql;
use Helpers\Trad\ITrad;
use Helpers\Trad\Trad;
use Helpers\Validator\Validator;
use Modules\Panier\Service\RequeteArticle;
use Modules\Commande\Repository\GareDeTriage;
use Helpers\Session\ParseBase1;

class GareDeTriageService
{
    /**
     * @var \PDO $pdo
     */
    public $pdo;

    /**
     * @var \PDO $pdoOxaFT
     */
    public $pdoOxaFT;

    /** @var array<mixed> $critereRegroupe */
    private $critereRegroupe;
    /** @var array<mixed> $post */
    private $post;

    /** @var string $fileName */
    private $fileName;


    /** @var string $numDATitreCde */
    private $numDATitreCde;

    /**
     * @var array<mixed> $bufferDevise
     */
    private $bufferDevise;
    /**
     * @var array<mixed> $bufferTauxDevise
     */
    private $bufferTauxDevise;

    private ITrad $trad;

    /**
     * @todo remove the dependency to ITrad
     * @param array<mixed> $post
     */
    public function __construct(\PDO $pdo, \PDO $pdoOxaFT, $post = [], ITrad $trad = null)
    {
        $this->pdo = $pdo;
        $this->pdoOxaFT = $pdoOxaFT;
        $this->trad = $trad;
        $this->numDATitreCde = Sql::paravrac($this->pdo, 'PARAMGEN', 'NUMDATITRES');

        if ($post) {
            $this->critereRegroupe = explode('/', $post['regroupement']);
            $this->post = $post;
            
            if (isset($_SESSION['GareDeTriage']['postSave']) && $_SESSION['GareDeTriage']['postSave'] == $post) {
            } else {
                $this->trieDA();
            }
        }

        if (isset($_SESSION['GareDeTriage']['fileName']) && $_SESSION['GareDeTriage']['fileName'] != '') {
            $this->fileName = $_SESSION['GareDeTriage']['fileName'];
        }
    }

    /**
     * fonction permetant de généré la gare de triage
     */
    private function trieDA() : void
    {
        $gareDeTriage = new GareDeTriage($this->pdo);
        $liste = $gareDeTriage->listeGareDeTriage($this->post);

        $intuition = new RequeteArticle($this->pdo, $this->pdoOxaFT, $_SESSION["Session_Login"], '', '');

        $dureTraitementDA = Sql::paravrac($this->pdo, 'PARAMGEN', 'DUREETTDA');

        $allDA = [];
        $arrayProjet = [];
        $keyTransco = [];
        $arrayDataProjet = [];
        $arrayDaParProjet = [];
        $arrayTitreDA = [];
        $arrayCommDA = [];
        $titre = [];

        $hastutil = new Hastutil($this->pdo);
        $user = $hastutil->find($_SESSION["Session_Login"]);

        if ($user['PRIXDACDE'] == '1' || $user['PRIXDACDE'] == '2') {
            $paramPrix = $user['PRIXDACDE'];
        } else {
            $paramPrix = Sql::paravrac($this->pdo, 'PARAMGEN', 'TYPE_INIT_PRIX_DA_CDE');
        }

        /** generation de la clause where pour les planning, les clause where et les PJ */
        $listeLigneDA = '';
        $count = 1;

        $arrayDA = [];
        $arrayReqLigneDA = [];
        foreach ($liste as $lign) {
            $arrayDA[$lign['NO_DA']] = $lign['NO_DA'];
            $allDA[$lign['NO_DA']] = $lign['NO_DA'];
            if ($listeLigneDA) {
                $listeLigneDA .= " or ";
            }

            $listeLigneDA .= " (da.NO_DA = :noDa$count and da.NO_PO = :noPo$count)";
            $arrayReqLigneDA[':noDa'.$count] = $lign['NO_DA'];
            $arrayReqLigneDA[':noPo'.$count] = $lign['NO_PO'];

            $count++;
        }

        /** génération de l'array des planning */
        $listeTempPlanning = [];
        if ($listeLigneDA != '' && !empty($arrayReqLigneDA)) {
            $listeTempPlanning = $gareDeTriage->getOptimalListPlanning($listeLigneDA, $arrayReqLigneDA);
        }

        $arrayPlanning = [];
        foreach ($listeTempPlanning as $plan) {
            $arrayPlanning[$plan['NO_DA']][$plan['NO_PO']][] = [
                'DTE_LIV' => $plan['DTE_LIV'],
                'QTE_DEMAN' => $plan['QTE_DEMAN'],
            ];
        }
        $fourniss = new Fourniss($this->pdo);

        /*$guId = Sql::guidGenerate();
        $arrayProjet[$guId] = [
            'key'                   => '',
            'libProjet'             => '',
            'arrayRegroup'          => [],
            'count'                 => 0,
            'frs'                   => [],
            'arrayDaParProjet'      => [],

            'TITRE'                 => '',
            'TITREedit'             => false,
            'listeTITRE'            => [],

            'listeCOMMENTAIRE'      => [],

            'entete'                => ['CODE_STE' => $this->post['societe'], 'DEVISE' => ''],
            'ligne'                 => [],
        ];*/

        foreach ($liste as &$ligne) {
            $bestFrsIntuition = null;
            $ligne['gardePrixDA'] = false;
            if ($paramPrix == '2') {
                $ligne['gardePrixDA'] = true;
            }

            $ligne['DA_CODE_FOU']   = $ligne['CODE_FOU'];
            $ligne['DA_PU']         = $ligne['PU'];
            $ligne['DA_REMISE']     = $ligne['TX_REMISE'];
            $ligne['DA_ACD']        = $ligne['ACD'];
            $ligne['QTE']           = $ligne['RAL'];

            $bestPrix = false;
            /* On regarde si la fournisseur a été selectionné sur une AO pour cette ligne */
            if ($ligne['FRS_AO'] != '') {
                if ($ligne['CODE_FOU'] == $ligne['FRS_AO']) {
                    $ligne['gardePrixDA'] = false;
                }
                $ligne['CODE_FOU'] = $ligne['FRS_AO'];
                $ligne['PU'] = $ligne['prixAO'];
                $ligne['ACD'] = '';
                $ligne['REMISE'] = '';
                $ligne['PROVENANCE'] = 'AO';

                $ligne['LIB_CODE_FOU']  = $ligne['AO_RS'];
                $ligne['DEVISE_FOU']    = $ligne['AO_DEVISE_FOU'];
                $ligne['MNTMINFAC']     = $ligne['AO_MNTMINFAC'];
                $ligne['MNTMINFRA']     = $ligne['AO_MNTMINFRA'];
                $ligne['RMINCPXN']      = $ligne['AO_RMINCPXN'];
                $bestPrix = true;
            } else {
                /* On recherche l'article dans la base intuition */
                $bestFrsIntuition = null;
                $bestPrixIntuition = null;
                if ((new \Modules\GlobalApplication\Service\LicenceService($this->pdo))->getLicenceOxacat() != 0 && $_SESSION['STATUT_RECH_ART'] != 0 && $_SESSION['STATUT_RECH_ART'] != -1) {
                    $bestIntuition = $intuition->searchBestArticle([
                        'COD_FAB' => $ligne['COD_FAB'],
                        'REF_FAB' => $ligne['REF_FAB'],

                        'REF_FOURN' => $ligne['REF_FOUR'],
                        'COD_FOURN' => $ligne['CODE_FOU'],

                        'COD_ART' => $ligne['CODE_ART'],
                    ], $ligne['RAL']);

                    $bestFrsIntuition = $bestIntuition['bestFrs'];
                    $bestPrixIntuition = $bestIntuition['bestPrix'];
                }

                /** On compare le resultat du meilleur fournisseur pour l'article depuis intuition et celui de la requete principal et on prend le meilleur
                 *  on le fait uniquement si le meilleur fournisseur intuition trouvé est le meme que la ligne de DA OU que la ligne de DA n'est pas de fournisseur
                 */
                if ($bestFrsIntuition && $bestFrsIntuition['PU'] > 0 && ($bestFrsIntuition['CODE_FOU'] == $ligne['CODE_FOU'] || $ligne['CODE_FOU'] == '')) {
                    if (($ligne['acd'] != '' && $bestFrsIntuition['ACD'] != '') || ($ligne['acd'] == '' && $bestFrsIntuition['ACD'] == '')) {
                        if (($ligne['FOURPREF'] && $bestFrsIntuition['FOURPREF']) || (!$ligne['FOURPREF'] && !$bestFrsIntuition['FOURPREF'])) {
                            if ($ligne['pu']>$bestFrsIntuition['PU']) {
                                $ligne['fournisseur'] = $bestFrsIntuition['CODE_FOU'];
                                $ligne['acd'] = $bestFrsIntuition['ACD'];
                                $ligne['pu'] = $bestFrsIntuition['PU'];
                                $ligne['remise'] = '0';
                                $ligne['PROVENANCE'] = $bestFrsIntuition['PROVENANCE'];
                                $ligne['ID_CAT_ORI'] = $bestFrsIntuition['ID_CAT'];
                                $ligne['DELAI_ACART'] = $bestFrsIntuition['DELAI'];
                            }
                        } elseif (!$ligne['FOURPREF'] && $bestFrsIntuition['FOURPREF']) {
                            $ligne['fournisseur'] = $bestFrsIntuition['CODE_FOU'];
                            $ligne['acd'] = $bestFrsIntuition['ACD'];
                            $ligne['pu'] = $bestFrsIntuition['PU'];
                            $ligne['remise'] = '0';
                            $ligne['PROVENANCE'] = $bestFrsIntuition['PROVENANCE'];
                            $ligne['ID_CAT_ORI'] = $bestFrsIntuition['ID_CAT'];
                            $ligne['DELAI_ACART'] = $bestFrsIntuition['DELAI'];
                        }
                    } elseif ($ligne['acd'] == '' && $bestFrsIntuition['ACD'] != '') {
                        $ligne['fournisseur'] = $bestFrsIntuition['CODE_FOU'];
                        $ligne['acd'] = $bestFrsIntuition['ACD'];
                        $ligne['pu'] = $bestFrsIntuition['PU'];
                        $ligne['remise'] = '0';
                        $ligne['PROVENANCE'] = $bestFrsIntuition['PROVENANCE'];
                        $ligne['ID_CAT_ORI'] = $bestFrsIntuition['ID_CAT'];
                        $ligne['DELAI_ACART'] = $bestFrsIntuition['DELAI'];
                    }
                }

                if ($bestPrixIntuition && $ligne['bestPrix'] > $bestPrixIntuition['PU']) {
                    $ligne['bestPrix'] = $bestPrixIntuition['PU'];
                }

                /* Si on a trouvé un prix pour l'article en question
                * (que la ligne n'est pas de fournisseur, ou que le fournisseur de la ligne = fournisseur trouvé (géré dans la requete))
                * alors on place l'acd, frs, prix et remise trouvé sur la ligne
                */

                if ($ligne['fournisseur'] != '') {
                    if ($ligne['fournisseur'] == $ligne['CODE_FOU'] || ($ligne['CODE_FOU'] == '' && $ligne['CODE_ART'] != '')) {
                        if ($ligne['CODE_FOU'] == '') {
                            $infoFrs = $fourniss->find($ligne['fournisseur'], ['RS', 'DEVISE', 'MNTMINFAC', 'MNTMINFRA', 'RMINCPXN']);

                            $ligne['LIB_CODE_FOU']  = $infoFrs['RS'];
                            $ligne['DEVISE_FOU']    = $infoFrs['DEVISE'];
                            $ligne['MNTMINFAC']     = $infoFrs['MNTMINFAC'];
                            $ligne['MNTMINFRA']     = $infoFrs['MNTMINFRA'];
                            $ligne['RMINCPXN']      = $infoFrs['RMINCPXN'];
                        }

                        if ($paramPrix != 2 || $ligne['CODE_FOU'] == '') {
                            $ligne['CODE_FOU'] = $ligne['fournisseur'];
                            $ligne['ACD'] = $ligne['acd'];
                            $ligne['PU'] =  $ligne['pu'];
                            $ligne['TX_REMISE'] = $ligne['remise'];
                            $bestPrix = true;
                            
                            if ($ligne['acd']) {
                                $ligne['nonModifiable'] = true;
                            }
                        } else {
                            $ligne['DELAI_ACART'] = null;
                        }
                    }
                }
            }

            /**
             * On applique par defaut, la devise du fournisseur, si le projet n'a pas de devise, alors la devise société.
             */
            if ($ligne['DEVISE_FOU']) {
                $devise = $ligne['DEVISE_FOU'];
            } else {
                $devise = $ligne['DEVISE_SOC'];
            }
            
            $ligne['prix_budget'] = false;

            if ($bestPrix) {
                $ligne['montantLigne'] = (floatval($ligne['PU'])*floatval($ligne['QTE'])) * (1-($ligne['TX_REMISE']/100));
            } else {
                $ligne['montantLigne'] = (floatval($ligne['PU'])*floatval($ligne['QTE']));
            }
            
            $ligne['PU_REMISE'] = floatval($ligne['PU'])*(1-($ligne['TX_REMISE']/100));
            if (Sql::boolSql($ligne['RMINCPXN'])) {
                $ligne['PU'] = $ligne['PU_REMISE'];
                $ligne['TX_REMISE'] = '0';
            }

            if ($ligne['BUDGET'] > $ligne['montantLigne']) {
                $ligne['montantLigne'] = $ligne['BUDGET'];
                $ligne['prix_budget'] = true;
            }

            $ligne['PLANNING'] = [];
            $ligne['DATE_LIMITE_TT_DA'] = '';

            $ligne['PLANNING'] = $arrayPlanning[$ligne['NO_DA']][$ligne['NO_PO']]??[];

            if ($ligne['DELAI_ACART']) {
                $traitement =  $dureTraitementDA + $ligne['DELAI_ACART'];
            } else {
                $traitement = $dureTraitementDA;
            }

            if (count($ligne['PLANNING']) > 1) {
                $ligne['DATE_LIMITE_TT_DA'] = date('Ymd', (int)strtotime($ligne['DTE_PLANN']. ' - '.$traitement.' days'));
                $ligne['planningActif'] = true;
            } else {
                $ligne['DATE_LIMITE_TT_DA'] = date('Ymd', (int)strtotime($ligne['DTELIVSOU']. ' - '.$traitement.' days'));
            }
            /* Critere de regroupement des projets en fonction des multiSelect */
            $key = '';
            $libProjet = [];
            $arrayRegroup = [];
            foreach ($this->critereRegroupe as $critere) {
                $key .= ($ligne[$critere]== ''? '000000000':$ligne[$critere]).'|';
                $arrayRegroup[$critere] = $ligne[$critere];
                                
                if (isset($ligne['LIB_'.$critere])) {
                    $libProjet[$critere] =  $ligne['LIB_'.$critere].' ('.$ligne[$critere].')';
                } else {
                    $libProjet[$critere] =  $ligne[$critere];
                }
            }

            /* Generate guid */
            if (empty($keyTransco[$key])) {
                $guId = Sql::guidGenerate();
                $keyTransco[$key] = $guId;
            } else {
                $guId = $keyTransco[$key];
            }

            /* Init liste DA présent  */
            $guIdLigne = Sql::guidGenerate();
            $arrayDataProjet[$guId][$guIdLigne] = $ligne;
            $arrayDaParProjet[$guId][$ligne['NO_DA']] = $ligne['NO_DA'];
            
            /* Init des TITRE */
            if (empty($arrayTitreDA[$guId][$ligne['NO_DA']]) && $ligne['TITRE'] != '') {
                if (empty($titre[$guId])) {
                    $titre[$guId] = '';
                }
                
                if ($this->numDATitreCde=='O') {
                    $titre[$guId] .= $this->trad->t('DA N°').' '.$ligne['NO_DA'].' : '.$ligne['TITRE'].'
';
                } else {
                    $titre[$guId] .= $ligne['TITRE'].'
';
                }

                $arrayTitreDA[$guId][$ligne['NO_DA']] = $ligne['TITRE'];
            }

            /* Init des COMMENTAIRE */
            if (empty($arrayCommDA[$guId][$ligne['NO_DA']]) && $ligne['COMM'] != '') {
                $arrayCommDA[$guId][$ligne['NO_DA']] = $ligne['COMM'];
            }

            $arrayProjet[$guId] = [
                'key'                   => $key,
                'libProjet'             => $libProjet,
                'arrayRegroup'          => $arrayRegroup,
                'count'                 => ($arrayProjet[$guId]['count']??0)+1,
                //'montantProjet'         => (($arrayProjet[$guId]['montantProjet']??0))+$montantLigne,
                'frs'                   => ['MNTMINFAC' => $ligne['MNTMINFAC'], 'MNTMINFRA' => $ligne['MNTMINFRA'], 'DEVISE' => $ligne['DEVISE_FOU'], 'RMINCPXN' => $ligne['RMINCPXN']],
                'arrayDaParProjet'      => $arrayDaParProjet[$guId],
                
                'TITRE'                 => ($titre[$guId]??''),
                'TITREedit'             => false,
                'listeTITRE'            => ($arrayTitreDA[$guId]??[]),
                
                'listeCOMMENTAIRE'      => ($arrayCommDA[$guId]??[]),
                
                'entete'                => ['CODE_STE' => $this->post['societe'], 'DEVISE' => $devise],
                'ligne'                 => $arrayDataProjet[$guId],
            ];
        }

        $listeDA = '';
        $listeDADoc = '';
        $arrayReqDA = [];
        $arrayReqDADoc = [];
        foreach ($allDA as $da) {
            if ($listeDA) {
                $listeDA .= " or ";
            }
            
            $listeDA .= " (da.NO_DA = :noDa$count)";
            $listeDADoc .= " (da.COD_ENR = :noDa$count)";
            $arrayReqDA[':noDa'.$count] = $da;
            $arrayReqDADoc[':noDa'.$count] = str_pad($da, 9, '0', STR_PAD_LEFT);
            
            $count++;
        }
        
        $listeClauseTmp = [];
        $listePJTmp = [];
        if ($listeDA != '' && !empty($arrayReqDA)) {
            $listeClauseTmp = $gareDeTriage->getOptimalListClause($listeDA, $arrayReqDA);
            $listePJTmp = $gareDeTriage->getOptimalListPJ($listeDA, $arrayReqDA);
        }
        //$listeDocTmp = $gareDeTriage->getOptimalListDoc($listeDADoc, $arrayReqDADoc);

        $listeClause = [];
        foreach ($listeClauseTmp as $clause) {
            $listeClause[$clause['NO_DA']][] = $clause;
        }

        $listePj = [];
        foreach ($listePJTmp as $pj) {
            $listePj[$pj['NO_DA']][] = $pj;
        }

        foreach ($arrayProjet as &$projet) {
            $this->initProjet($projet);
            $this->calculMontantProjet($projet);
            
            // calcule du montant du projet dans la devise du projet²

            foreach ($projet['arrayDaParProjet'] as $da) {
                if (isset($listeClause[$da])) {
                    foreach ($listeClause[$da] as $clause) {
                        $projet['clause'][] = $clause;
                    }
                }
        
                if (isset($listePj[$da])) {
                    foreach ($listePj[$da] as $pj) {
                        $projet['pj'][] = $pj;
                    }
                }
            }
        }

        $key = array_column($arrayProjet, 'key');
        array_multisort($key, SORT_ASC, SORT_STRING, $arrayProjet);

        foreach ($arrayProjet as &$projet) {
            $key = array_column($projet['ligne'], 'NO_DA');
            array_multisort($key, SORT_ASC, SORT_NUMERIC, $projet['ligne']);
        }

        $_SESSION['GareDeTriage']['postSave'] = $this->post;

        $this->saveFile($arrayProjet);
    }

    /**
     * Permet d'enregistrer' sur tmp le fichier contenant le resultat de la gare de triage
     * Permet d'enregistrer l'intégralité des projets ou uniquement un projet
     * @param array<mixed> $array
     */
    public function saveFile($array, string $idprojet = null) : void
    {
        if ($idprojet) {
            $arrayProjet = $this->getProjet();

            $arrayProjet[$idprojet] = $array;

            $arraySave = $arrayProjet;
        } else {
            $arraySave = $array;
        }

        if (!$this->fileName) {
            $this->fileName = 'file_gareDeTriage'.$_SESSION['id_user'].random_int(0, 999999999).'.txt';
            $_SESSION['GareDeTriage']['fileName'] = $this->fileName;
        }

        Fichier::createFichierTmp($this->fileName, (string)json_encode($arraySave));
    }

    /**
     * Permet de récuperé 1 projet ($idProjet) ou l'intégralité des projets.
     * @return array<mixed>
     */
    public function getProjet(string $idprojet = null)
    {
        $fileProjet = file_get_contents((new ParseBase1())->getRep()->tmp.$this->fileName);
        $arrayProjet = json_decode((string)$fileProjet, true);

        if ($idprojet) {
            return $arrayProjet[$idprojet];
        } else {
            return $arrayProjet;
        }
    }

    /**
     * return les critères de regroupement
     * @return array<mixed>
     */
    public function getCritere()
    {
        return $this->critereRegroupe;
    }
    

    /**
     * initialise les valeurs d'entête d'un projet de commande
     * @param array<mixed> $projet
     */
    public function initProjet(&$projet) : void
    {
        $listeFrs = [];
        $ligneLangue = [];
        $listeCtrEmetteur = [];
        $listeCtrLivraison = [];
        $listeDevise = [];
        $listeSectimp = [];
        $listeCdc = [];
        $listeSScana = [];
        $listeTypeDoc = [];
        $listeModTrans = [];

        foreach ($projet['ligne'] as $ligne) {
            if ($ligne['CODE_FOU']) {
                $listeFrs[$ligne['CODE_FOU']] = $ligne['CODE_FOU'];
            }

            if ($ligne['COD_LNG']) {
                $ligneLangue[$ligne['COD_LNG']] = $ligne['COD_LNG'];
            }

            if ($ligne['DAENT_CENTRE_EMETTEUR']) {
                $listeCtrEmetteur[$ligne['DAENT_CENTRE_EMETTEUR']] = $ligne['DAENT_CENTRE_EMETTEUR'];
            }

            if ($ligne['CTRLIVR']) {
                $listeCtrLivraison[$ligne['CTRLIVR']] = $ligne['CTRLIVR'];
            }

            if ($ligne['MOD_TRS']) {
                $listeModTrans[$ligne['MOD_TRS']] = $ligne['MOD_TRS'];
            }

            if ($ligne['DEVISE']) {
                $listeDevise[$ligne['DEVISE']] = $ligne['DEVISE'];
            }

            if ($ligne['SECTIMP']) {
                $listeSectimp[$ligne['SECTIMP']] = $ligne['SECTIMP'];
            }

            if ($ligne['CODE_COMP']) {
                $listeCdc[$ligne['CODE_COMP']] = $ligne['CODE_COMP'];
            }

            if ($ligne['SSCPTEANA']) {
                $listeSScana[$ligne['SSCPTEANA']] = $ligne['SSCPTEANA'];
            }
            if ($ligne['TYP_DOC']) {
                $listeTypeDoc[$ligne['TYP_DOC']] = $ligne['TYP_DOC'];
            }
        }

        if (count($listeFrs) == 1 && ($projet['entete']['CODE_FOU']??'') == '') {
            $projet['entete']['CODE_FOU'] = (string) array_key_first($listeFrs);

            $tycTacfou = new TacFyfo($this->pdo);
            $projet['entete']['COD_TAC'] = $typeAchat = $tycTacfou->find(['TACFOFOU' => $projet['entete']['CODE_FOU'], 'TACFODEF' => 'T'])['TACFOTAC']??'';

            if (!$typeAchat) {
                $projet['entete']['COD_TAC'] = sql::paravrac($this->pdo, 'PARAMFOU', 'INITTAC');
                $projet['entete']['confirmationAchat'] = true;
                $projet['entete']['LOCK_confirmationAchat'] = true;
            }
        }
        
        if (count($ligneLangue) == 1 && ($projet['entete']['CODE_LNG']??'') == '') {
            $projet['entete']['COD_LNG'] = array_key_first($ligneLangue);
        }

        if (count($listeCtrEmetteur) == 1 && ($projet['entete']['CTR_EMETT']??'') == '') {
            $projet['entete']['CTR_EMETT'] = array_key_first($listeCtrEmetteur);
        }

        if (count($listeCtrLivraison) == 1 && ($projet['entete']['CTR_LIV']??'') == '') {
            $projet['entete']['CTR_LIV'] = array_key_first($listeCtrLivraison);
        }

        if (count($listeModTrans) == 1 && ($projet['entete']['MOD_TRS']??'') == '') {
            $projet['entete']['MOD_TRS'] = array_key_first($listeModTrans);
        }

        if (count($listeDevise) == 1 && ($projet['entete']['DEVISE']??'') == '') {
            $projet['entete']['DEVISE'] = array_key_first($listeDevise);
        }

        if (count($listeSectimp) == 1 && ($projet['entete']['SECTIMP']??'') == '') {
            $projet['entete']['SECTIMP'] = array_key_first($listeSectimp);
        }

        if (count($listeCdc) == 1 && ($projet['entete']['CODECOMP']??'') == '') {
            $projet['entete']['CODECOMP'] = array_key_first($listeCdc);
        }

        if (count($listeSScana) == 1 && ($projet['entete']['SSCPTEANA']??'') == '') {
            $projet['entete']['SSCPTEANA'] = array_key_first($listeSScana);
        }

        if (count($listeTypeDoc) == 1 && ($projet['entete']['TYP_DOC']??'') == '') {
            $projet['entete']['TYP_DOC'] = array_key_first($listeTypeDoc);
        }
    }

    /**
     * Initialise les clauses, pj, document d'un projet de commande depuis une DA
     * @param array<mixed> $projet
     * @param array<mixed> $arrayNewDa
     * @param bool $updateInit
     */
    public function initClausePjDocProjet(&$projet, $updateInit = false, $arrayNewDa = []) : void
    {
        $gareDeTriage = new GareDeTriage($this->pdo);

        $listeDA = '';
        $listeDADoc = '';
        $arrayReqDA = [];
        $arrayReqDADoc = [];
        $count = 1;

        $arrayDA = [];

        if ($updateInit) {
            $arrayDA = $arrayNewDa;
        } else {
            $arrayDA = $projet['arrayDaParProjet'];
        }

        foreach ($arrayDA as $da) {
            // TOOD : use implode instead
            if ($listeDA) {
                $listeDA .= " or ";
                $listeDADoc .= " or ";
            }

            $listeDA .= " (da.NO_DA = :noDa$count)";
            $listeDADoc .= " (da.COD_ENR = :noDa$count)";
            $arrayReqDA[':noDa'.$count] = $da;
            $arrayReqDADoc[':noDa'.$count] = str_pad($da, 9, '0', STR_PAD_LEFT);

            $count++;
        }

        $listeClause = $gareDeTriage->getOptimalListClause($listeDA, $arrayReqDA);
        $listePJ = $gareDeTriage->getOptimalListPJ($listeDA, $arrayReqDA);
        $listeDoc = $gareDeTriage->getOptimalListDoc($listeDADoc, $arrayReqDADoc);

        foreach ($listeClause as $clause) {
            $projet['clause'][] = $clause;
        }

        foreach ($listePJ as $pj) {
            $projet['pj'][] = $pj;
        }

        foreach ($listeDoc as $doc) {
            $projet['document'][] = $doc;
        }
    }

    /**
     * Calcule le montant ttc et ht d'un projet
     * @param array<mixed> $projet
     */
    public function calculMontantProjet(&$projet) : void
    {
        $gareDeTriageRepo = new GareDeTriage($this->pdo);
        $deviseEntity = new Devise($this->pdo);

        $taux = [];
        foreach ($projet['ligne'] as $ligne) {
            if (empty($this->bufferTauxDevise[$projet['entete']['DEVISE']][$ligne['DEVISE_SOC']])) {
                $taux[$ligne['DEVISE_SOC']] = $ligne['DEVISE_SOC'];
            }
        }

        if (empty($this->bufferDevise[$projet['entete']['DEVISE']])) {
            $devise = $deviseEntity->find($projet['entete']['DEVISE']);
            $this->bufferDevise[$projet['entete']['DEVISE']] = $devise;
        }

        $listeTaux = $gareDeTriageRepo->getListeTaux($projet['entete']['DEVISE'], $taux);
        foreach ($listeTaux as $val) {
            $this->bufferTauxDevise[$projet['entete']['DEVISE']][$val['DEV_PIVOT']] = $val;
        }

        $totalProjet = 0;
        foreach ($projet['ligne'] as $ligne) {
            $montant = $ligne['montantLigne'];

            if ($ligne['DEVISE'] == $projet['entete']['DEVISE']) {
                $totalProjet += $montant;
            } else {
                $txDAversSOC = 0;
                if ($ligne['DEVISE'] == $ligne['DEVISE_SOC']) {
                    $txDAversSOC  = 1;
                } elseif ($ligne['DEVISE_SOC'] == $_SESSION['parametrage']['DEVISE_BASE']) {
                    $txDAversSOC = $ligne['TAUX_DEV_SOC'];
                } else {
                    $txDAversSOC = $ligne['TAUX_DEV_BDD'];
                }

                if ($txDAversSOC == 0) {
                    $txDAversSOC = 1;
                }

                if ($ligne['DEVISE_SOC'] == $projet['entete']['DEVISE']) {
                    $txPROJversSOC = 1;
                } elseif ($ligne['DEVISE_SOC'] == $_SESSION['parametrage']['DEVISE_BASE']) {
                    $devise = $this->bufferDevise[$projet['entete']['DEVISE']] ;
                    $txPROJversSOC = $devise['VALEUR'];
                } else {
                    $taux = $this->bufferTauxDevise[$projet['entete']['DEVISE']][$ligne['DEVISE_SOC']];
                    $txPROJversSOC = $taux['TAUX'];
                }

                if ($txPROJversSOC == 0) {
                    $txPROJversSOC = 1;
                }

                $totalProjet += $ligne['montantLigne'] * $txDAversSOC / $txPROJversSOC;
            }
        }

        $projet['montantProjet'] = number_format($totalProjet, 2, '.', '');
        $projet['montantTTC'] = number_format($totalProjet, 2, '.', '');
    }

    /**
     * Permet de supprimer les clause, pj, doc, titre et commentaire lié a une DA si celle-ci ne fait plus partie du projet
     * (si on déplace une ligne de DA d'un projet, on contrôle l'existance d'une autre ligne de DA et on supprime si elle n'est pas présente)
     * @param array<mixed> $fileContent
     */
    public function removeDAOldProjet(&$fileContent, string $guidDA, string $oldProjet) : void
    {
        
        $ligne = $fileContent[$oldProjet]['ligne'][$guidDA];
        //$fileContent[$oldProjet]['montantProjet'] -= $ligne['montantLigne'];
        $fileContent[$oldProjet]['count'] = (int) $fileContent[$oldProjet]['count'] - 1;
        
        unset($fileContent[$oldProjet]['ligne'][$guidDA]);

        /*  on verifie qu'après avoir déplacé la ligne, l'existance d'autre ligne de DA de la même DA  */
        $daExist = false;
        foreach (($fileContent[$oldProjet]['ligne'] ?? []) as $da) {
            if ($da == $ligne['NO_DA']) {
                $daExist = true;
                break;
            }
        }

        /* si le projet n'a plus de ligne, alors on le supprime */
        if (count($fileContent[$oldProjet]['ligne'] ?? []) === 0) {
            unset($fileContent[$oldProjet]);
        } else {
            /* si la da n'existe plus, on va vérifier dans les Titre, commentaire, clause, piece jointe et document si il existe, on va les supprimer de l'ancien projet */
            if (!$daExist) {
                /* on supprime la DA de la liste des DA du projet */
                unset($fileContent[$oldProjet]['arrayDaParProjet'][$ligne['NO_DA']]);
                /* On supprime les titre de la DA du projet */
                unset($fileContent[$oldProjet]['listeTITRE'][$ligne['NO_DA']]);
                /* on supprime les commentaire de la DA du projet */
                unset($fileContent[$oldProjet]['listeCOMMENTAIRE'][$ligne['NO_DA']]);
                
                /* On regenere le titre compilé du projet sans celui de la DA retiré */
                if (!$fileContent[$oldProjet]['TITREedit']) {
                    $titre = '';
                    foreach ($fileContent[$oldProjet]['ligne'] as $lign) {
                        /* Init des TITRE */
                        if ($lign['TITRE'] != '') {
                            if ($this->numDATitreCde=='O') {
                                $titre .= $this->trad->t('DA N°').' '.$lign['NO_DA'].' : '.$lign['TITRE'].'
';
                            } else {
                                $titre .= $lign['TITRE'].'
';
                            }
                        }
                    }

                    $fileContent[$oldProjet]['TITRE'] = $titre;
                }

                /* On retire les clauses de la DA */
                foreach (($fileContent[$oldProjet]['clause']??[]) as $key => $clause) {
                    if ($clause['NO_DA'] == $ligne['NO_DA']) {
                        unset($fileContent[$oldProjet]['clause'][$key]);
                    }
                }

                /* on retire les PJ de la DA */
                foreach (($fileContent[$oldProjet]['pj']??[]) as $key => $pj) {
                    if ($pj['NO_DA'] == $ligne['NO_DA']) {
                        unset($fileContent[$oldProjet]['pj'][$key]);
                    }
                }

                /* on retire les documents de la DA */
                foreach (($fileContent[$oldProjet]['document']??[]) as $key => $doc) {
                    $idDoc = str_pad($ligne['NO_DA'], 9, '0', STR_PAD_LEFT);
                    if ($doc['COD_ENR'] == $idDoc) {
                        unset($fileContent[$oldProjet]['document'][$key]);
                    }
                }
            }
            
            $this->calculMontantProjet($fileContent[$oldProjet]);
        }
    }

    /**
     * Permet le déplacement de déplace une ligne de DA d'un projet vers un autre, et on regenère tout les éléments liés
     * @param array<mixed> $listeDA
     */
    public function switchDANewProjet(ITrad $trad, array $listeDA, string $newProjet) : void
    {
        $fileContent = $this->getProjet();

        $arrayNewDa = [];
        foreach ($listeDA as $oldProjet => $guidDA) {
            $guidDA = $guidDA[0];
            $ligne = $fileContent[$oldProjet]['ligne'][$guidDA];

            $this->removeDAOldProjet($fileContent, $guidDA, $oldProjet);
            
            if (empty($fileContent[$newProjet]['arrayDaParProjet'][$ligne['NO_DA']])) {
                $arrayNewDa[$ligne['NO_DA']] = $ligne['NO_DA'];

                if ($ligne['TITRE']) {
                    $fileContent[$newProjet]['listeTITRE'][$ligne['NO_DA']] = $ligne['TITRE'];
                    $fileContent[$newProjet]['TITRE'] .= $trad->t('DA N°').' '.$ligne['NO_DA'].' '.$ligne['TITRE'].'
';
                }
                if ($ligne['COMM']) {
                    $fileContent[$newProjet]['listeCOMMENTAIRE'][$ligne['NO_DA']] = $ligne['COMM'];
                }
            }
    
            $fileContent[$newProjet]['ligne'][$guidDA] = $ligne;
            $fileContent[$newProjet]['arrayDaParProjet'][$ligne['NO_DA']] = $ligne['NO_DA'];

            //$fileContent[$newProjet]['montantProjet'] += $ligne['montantLigne'];
            $fileContent[$newProjet]['count'] = (int)$fileContent[$newProjet]['count']+1;
        }

        $this->calculMontantProjet($fileContent[$newProjet]);
        $this->initClausePjDocProjet($fileContent[$newProjet], true, $arrayNewDa);

        $this->saveFile($fileContent);
    }

    /**
     * permet de valider les valeurs d'entête d'un projet
     */
    public function validatorProjet(ITrad $trad, Validator &$validator, string $idProjetDrop, string $idProjetSrc, string $idLigneSrc) : void
    {
        $fileContent = $this->getProjet();

        $enteteProjetSrc = $fileContent[$idProjetDrop]['entete'];
        $ligneProjet = $fileContent[$idProjetSrc]['ligne'][$idLigneSrc];

        $listeChamps = [
            [
                'ENTETE' => 'CODE_FOU',
                'LIGNE' => 'CODE_FOU',
                'texte' => $trad->t('Le fournisseur'),
                'text_fem' => false,
            ],
            [
                'ENTETE' => 'COD_LNG',
                'LIGNE' => 'COD_LNG',
                'texte' => $trad->t('La langue'),
                'text_fem' => true,
            ],
            [
                'ENTETE' => 'CTR_EMETT',
                'LIGNE' => 'DAENT_CENTRE_EMETTEUR',
                'texte' => $trad->t('Le centre émetteur'),
                'text_fem' => false,
            ],
            [
                'ENTETE' => 'CTR_LIV',
                'LIGNE' => 'CTRLIVR',
                'texte' => $trad->t('Le centre de livraison'),
                'text_fem' => false,
            ],
            [
                'ENTETE' => 'DEVISE',
                'LIGNE' => 'DEVISE',
                'texte' => $trad->t('La devise'),
                'text_fem' => true,
            ],
            [
                'ENTETE' => 'SECTIMP',
                'LIGNE' => 'SECTIMP',
                'texte' => $trad->t('La section d\'imputation'),
                'text_fem' => true,
            ],
            [
                'ENTETE' => 'CODECOMP',
                'LIGNE' => 'CODE_COMP',
                'texte' => $trad->t('Le code complémentaire'),
                'text_fem' => false,
            ],
            [
                'ENTETE' => 'SSCPTEANA',
                'LIGNE' => 'SSCPTEANA',
                'texte' => $trad->t('Le sous-compte d\'analyse'),
                'text_fem' => false,
            ],
            [
                'ENTETE' => 'TYP_DOC',
                'LIGNE' => 'TYP_DOC',
                'texte' => $trad->t('Le type de document'),
                'text_fem' => false,
            ],
        ];
        
        foreach ($listeChamps as $champs) {
            // TODO : simplify
            if (($enteteProjetSrc[$champs['ENTETE']]??'') != ''
                && ($ligneProjet[$champs['LIGNE']]??'') != ''
                && $enteteProjetSrc[$champs['ENTETE']] != $ligneProjet[$champs['LIGNE']]
            ) {
                $validator->setError(trad::strBuild(
                    $champs['text_fem'] ?
                        $trad->t('@1@ de la ligne de DA @2@/@3@ (@4@) est différente de celle du projet de commande (@5@).') :
                        $trad->t('@1@ de la ligne de DA @2@/@3@ (@4@) est différent de celui du projet de commande (@5@).'),
                    $champs['texte'],
                    $ligneProjet['NO_DA'],
                    $ligneProjet['NO_PO'],
                    $ligneProjet[$champs['LIGNE']],
                    $enteteProjetSrc[$champs['ENTETE']]
                ));
            }
        }
    }
}
