<?php
namespace Modules\Panier\Service;

use Entity\Model\Articles;
use Entity\Model\CCLDoc;
use Entity\Model\Codgest;
use Entity\Model\Fourniss;
use Entity\Model\OxaUserPanierCsDon;
use Entity\Model\Paravrac;
use Helpers\Outil\Outils;
use Helpers\Outil\Sql;
use Entity\Model\OxaUserPanierLigne;
use Entity\Model\OxaUserPanierLigneFour;
use Helpers\CaracCompl\CaracCompl;
use Modules\Ajax\Repository\Listes;
use Modules\GlobalApplication\Outil\InitAxesImpCde;
use Modules\GlobalApplication\Outil\InitAxesImpDa;
use Modules\GlobalApplication\Service\ConvertionDeviseService;
use Modules\Panier\Repository\PanierFrs;
use Modules\Panier\Service\RequeteArticle;
use Modules\Panier\Repository\PanierEntete;
use Modules\Panier\Repository\PanierLigne;
use Modules\Panier\Service\ArticleAssocie;
use Helpers\Parametres\Constante;
use Modules\RechercheArticles\Service\OutilArticleService;

class PanierLigneService
{
    /**
     * @var array<mixed> $entete
     */
    private $entete;

    /**
     * @var array<mixed> $listeArtEdit
     */
    private $listeArtEdit;

    /**
     * @var array<mixed> $listeErrorFraisPort
     */
    public $listeErrorFraisPort;

    private \PDO $pdo;
    private \PDO $pdoOxaFT;
    private PanierEntete $panierEntete;
    private PanierLigne $panierLigne;
    private OutilPanierService $OutilPanierService;
    private CalculTauxTvaService $calculTauxTvaService;
    private string $contexte;
    private bool $affichageTVA;
    private int $decimalPU;
    
    public function __construct(\PDO $pdo, \PDO $pdoOxaFT, string $contexte)
    {
        $this->pdo              = $pdo;
        $this->pdoOxaFT         = $pdoOxaFT;

        $this->panierEntete     = new PanierEntete($this->pdo);
        $this->panierLigne      = new PanierLigne($this->pdo);
        $this->OutilPanierService = new OutilPanierService($this->pdo, $this->pdoOxaFT);
        $this->calculTauxTvaService = new CalculTauxTvaService($this->pdo);
        
        $this->contexte = $contexte;
        
        $this->decimalPU = Constante::PUDECIMAL;
        $this->affichageTVA = Sql::paravrac($this->pdo, 'OXAPROC', 'AFFTTC') == 'O';

        $this->listeErrorFraisPort = [];

        if ($this->contexte == 'panier') {
        }

        $this->entete = $this->panierEntete->getEntetePanier($_SESSION['id_panier'], $_SESSION['id_user']);
    }

    /**
     * donne la liste des articles ajouter/modifier apres l'ajout/modif qte/suppresion d'un article afin d'actualisé l'affichage de la recherche article
     * @return array<mixed>
     */
    public function getListeArticleEdit()
    {
        return $this->listeArtEdit;
    }
    
    private function addListeArtEdit(
        float $qte,
        string $idLigne,
        string $rowCompteur = null,
        float $prixArt = 0,
        float $qteCond = 1,
        float  $tva = null,
        string $codDev = null,
        string $unite = '',
        string $libUnite = '',
    ) : void {
        $prix = $prixArt * $qteCond;
        if ($tva) {
            $prixTva = $prix * (1 + $tva / 100);
        } else {
            $prixTva = $prix;
        }

        $decimal = Outils::getUniteDecimal($this->pdo, $unite);

        $prixCalcul = ($this->affichageTVA? $prixTva:$prix);
        $prixAff = number_format($prixCalcul, $this->decimalPU, '.', ' ');
        $montant = number_format($prixCalcul * $qte, Constante::montantDecimal, '.', ' ');

        $this->listeArtEdit[] = [
            'ROW_COMPTEUR'  => $rowCompteur,
            'qte'           => number_format($qte, $decimal, '.', ' '),
            'PU'            => $prixAff,
            'devise'        => $codDev,
            'idLig'         => $idLigne,
            'unite'         => $libUnite,
            'montant'       => $montant
        ];
    }

    /**
     * @return array<mixed>
     */
    public function getListeMontantByCritere()
    {
        $listeArticle = $this->listeArtEdit;

        $listeLigne = [];
        foreach ($listeArticle as $article) {
            $listeLigne[] = $article['idLig'];
        }

        $listeCritereUpdate = $this->panierLigne->getMontantByCritere($_SESSION['id_user'], $_SESSION['id_panier'], $listeLigne);
        
        $listeCritere = [];
        foreach ($listeCritereUpdate as $critere) {
            $idCritere = (string)str_replace('|', Constante::oxaPipe, $critere['CRITERE_REGROUP']);

            $montantCalcul = ($this->affichageTVA? $critere['montantCritereTTC']:$critere['montantCritere']);
            $montantAnnexesCalcul = ($this->affichageTVA? $critere['montantAnnexesCritereTTC']:$critere['montantAnnexesCritere']);
            $montant = number_format($montantCalcul, Constante::montantDecimal, '.', ' ');

            if ($montantAnnexesCalcul) {
                $montantAnnexes = number_format($montantAnnexesCalcul, Constante::montantDecimal, '.', ' ');
            } else {
                $montantAnnexes = number_format(0, Constante::montantDecimal, '.', ' ');
            }
            $listeCritere[$idCritere] = [
                'montant' => $montant,
                'montantAnnexes' => $montantAnnexes
            ];
        }

        return $listeCritere;
    }

    /**
     * @param array<mixed> $article
     * @param float $qte
     * @param array<mixed> $arrayCompl
     * @param array<mixed> $listeValueCC
     */
    public function addPanier(
        $article,
        $qte,
        $arrayCompl = [],
        bool $modeFils = false,
        bool $modeImport = false,
        $listeValueCC = [],
        bool $initImpu = false,
        string $idPanier = null,
        string $idUser = null
    ) :string {
        $qte = floatval($qte);
        $idPanier = is_null($idPanier)? $_SESSION['id_panier']:$idPanier;
        $idUser   = is_null($idUser)? $_SESSION['id_user']:$idUser;

        (new PanierEnteteService($this->pdo))->initCS($idPanier, $idUser);
        
        /*
         * 0 => article catalogue,
         * 1 article genererique / famille / Libre,
         * 2 article de types frais annexe,
         * 3 article de frais de transport (automatique)
         */
        $type_de_ligne = $article['type_de_ligne'] ?? 0;

        $initCC                 = $arrayCompl['initCC']??true;
        /* dans la V1 ces value sont init dans la fonction, a voir en V2 */
        $FIN_DEB_PER            = $arrayCompl['FIN_DEB_PER']??'F';
        $RECEPAUTO_JOUR         = $arrayCompl['RECEPAUTO_JOUR']??0;
        $DATEDEBCONT            = $arrayCompl['DATEDEBCONT']??'00000000';
        $DATEFINCONT            = $arrayCompl['DATEFINCONT']??'00000000';
        $articleObligatoire     = $arrayCompl['articleObligatoire']??false;

        $si                     = $arrayCompl['SI']??'';
        $sca                    = $arrayCompl['SCA']??'';
        $cdc                    = $arrayCompl['CDC']??'';
        $cg                     = $arrayCompl['CG']??'';

        $dteLivr                = $arrayCompl['dteLivr']??'';
        $codeMet                = $arrayCompl['codeMet']??'';
        $codeSpe                = $arrayCompl['codeSpe']??'';
        $REFLMAN                = $arrayCompl['REFLMAN']??'';

        $chargerPanier          = $arrayCompl['chargerPanier']??false;

        $panierEntete = $this->entete;

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

        if ($article['COD_ART']??'') {
            $articleHAPLUs = (new Articles($this->pdo))->find($article['COD_ART'], ['SSFAM']);
            $article['COD_SFAM'] = $articleHAPLUs['SSFAM'];
        }
        
        if ($arrayCompl['centreLivraisonLigne']??'') {
            $centreLivraison = $arrayCompl['centreLivraisonLigne'];
        } else {
            $centreLivraison    = $panierEntete['LIV_CTR'];
        }

        $modTransport       = $panierEntete['MOD_TRS'];
        $noCde              = $panierEntete['NO_CDE'];
        
        if (!$modeImport || $initImpu) {
            $codeGestion = new Codgest($this->pdo);
            $infoCG = $codeGestion->find([
                'CODE_STE'  => $this->entete['CODE_STE'],
                'CODE_SI'   => $this->entete['SI_CODE'],
                'CODE_AFF'  => $this->entete['CG_CODE']
            ]);

            $axeEntete = [
                'CODE_STE'  => $this->entete['CODE_STE'],
                'SECTIMP'   => $this->entete['SI_CODE'],
                'SSCPTEANA' => $this->entete['SCA_CODE'],
                'CODECOMP'  => $this->entete['CDC_CODE'],
                'TYP_DOC'   => '',
    
                'ID_CG'     => $infoCG['CODE_GES']??'',
                'CODGES'    => $infoCG['CODE_AFF']??'',
                'LIBGES'    => $infoCG['LIB_GES']??'',
            ];
            
            $initImputation = $noCde ?
                new InitAxesImpCde($this->pdo, $axeEntete):
                new InitAxesImpDa($this->pdo, $axeEntete);
            $imputation = $initImputation->getInitImputation([
                'CODE_ART' => ($article['COD_ART']??''),
                'SousFamille' => [
                    'CODE_SFA' => $article['COD_SFAM']??'',
                    'CODE_FAM' => $article['CODE_FAM']??'',
                ],
            ]);

            /*$initImpu = new InitAxesImputations($this->pdo, $noCde? 'CDE':'DA', '', $axeEntete);
            $imputation = $initImpu->getInitImputation(($article['COD_ART']??''), ($article['COD_SFAM']??''), ($article['CODE_FAM']??''));*/
    
            $saveSi = $si;
            if (!$si || $initImpu) {
                $si = $imputation['SI'];
            }
            if (!$cdc || $initImpu) {
                $cdc = $imputation['CDC'];
            }
            if (!$sca || $initImpu) {
                $sca = $imputation['SCA'];
            }
            if (!$cg || $saveSi != $si || $initImpu) {
                $cg = $imputation['CODGES'];
            }
            
            $specifique = new \Helpers\Additional\Specifique\Specifique();
            $namespaceSpecifique = $specifique->specifiqueFunction('\\Modules\\Panier\\Service\\SpecPanierLigneService');
            if (class_exists($namespaceSpecifique)) {
                $cg = \Helpers\Additional\Specifique\Specifique::specifique('\\Modules\\Panier\\Service\\SpecPanierLigneService', 'majCGBouygue', $this->pdo, $cg, $si, $_SESSION['id_panier'], $article['COD_SFAM']);
            }
        }
        
        // Attention dans le cas de conditionnement alors le prix unitaire est deja multiplié donc il faut le divisé
        if (($article['TXTCOND']??0) > 0 && $article['CONDITNT'] > 0) {
            $article['PX_ART'] = $article['PX_ART'] / $article['CONDITNT'];
        }

        $critereArticle = CritereRegroupService::generateCritere([
            'COD_FOURN'         => $article['COD_FOURN']??'',
            'COD_DEV'           => $article['DEVISE']??'',
            'CodeCtrLivraison'  => $centreLivraison,
            'MODE_TRS'          => $modTransport,
            'SI_CODE'           => $si
        ]);

        if (($article['COD_FOURN']??'') && $article['COD_FOURN']!=Constante::fournisseurStock) {
            $fourniss = new Fourniss($this->pdo);
            $infoFrs = $fourniss->find($article['COD_FOURN'], ['RS', 'RECEP_AUTO']);
            $article['RS_FOURN'] = $infoFrs['RS']??'';

            $critere = [
                'COD_FOURN' => $article['COD_FOURN'],
                'CRITERE_REGROUP' => $critereArticle,
            ];

            $infoFrsPanier = $this->panierEntete->getInfoFourPanier($critere);
            if ($this->contexte == 'MOBILITE') {
                $article['RECEP_AUTO'] = Sql::boolSql($article['RECEP_AUTO']);
            } elseif (($article['RECEP_AUTO']??null) || Sql::boolSql($infoFrs['RECEP_AUTO'])) {
                $FIN_DEB_PER = 'F';
                $RECEPAUTO_JOUR = 31;
                $DATEDEBCONT = $article['DATEDEBCONT'] ?? $infoFrsPanier['DATEDEBCONT'] ?? '00000000';
                $DATEFINCONT = $article['DATEFINCONT'] ?? $infoFrsPanier['DATEFINCONT'] ?? '00000000';
                $periodicite = $infoFrsPanier['PER_REC_AUTO'] ?? 'M';

                $article['RECEP_AUTO'] = Sql::boolSql(true);
            } else {
                $article['RECEP_AUTO'] =  Sql::boolSql($article['RECEP_AUTO']);
            }
        }
        
        if (($article['COD_SFAM']??'')) {
            $liste = new Listes($this->pdo);
            $article['LIB_SFAM'] = $liste->Sousfamille(['filter_egal_CODE_SFA' => $article['COD_SFAM']], 'DESIGNAT')[0]['DESIGNAT']??'';
        }

        // controle nombre ligne dans le panier si panier = 0
        $article['PX_ART_INIT'] = array_key_exists('PX_ART_INIT', $article)? ($article['PX_ART_INIT']??''):($article['PX_ART']??'');
        if (($article['PRIXDEGRESSIF']??false)) {
            $article['PU']       =  $article['PX_ART'];
            $article['PU_INIT']  =  $article['PX_ART_INIT'];
            
            $article['PX_ART'] = $requeteArticle->getPrixDegressifByQte($article, $qte);
        }

        /* Init date de livraison */
        $param = [
            'LIGCAT_PASINITDTELIV' => sql::paravrac($this->pdo, 'OXAPROC', 'LIGCAT_PASINITDTELIV'),
            'LIGMAN_PASINITDTELIV' => sql::paravrac($this->pdo, 'OXAPROC', 'LIGMAN_PASINITDTELIV')
        ];

        if ($type_de_ligne=='0' && $param['LIGCAT_PASINITDTELIV'] == 'O') {
            $initDelaiLiv  = false;
        } elseif ($type_de_ligne=='1' && $param['LIGMAN_PASINITDTELIV'] == 'O') {
            $initDelaiLiv  = false;
        } else {
            $initDelaiLiv  = true;
        }

        if (empty($article['DELAI'])) {
            $article['DELAI'] = 0;
        }

        $traitementDA = (int) (new Paravrac($this->pdo))->getValue('PARAMGEN', 'DUREETTDA');

        if ($this->contexte  == 'CREEAO' || $this->contexte  == 'IMPORT') {
            if ($initDelaiLiv ||  $article['DELAI'] != 0) {
                if (!$dteLivr) {
                    $dteLivr = OutilPanierService::getDateLivraisonMin($article['DELAI'], $traitementDA);
                }
            } else {
                $dteLivr = '00000000';
            }
        } elseif (PanierService::panierRegul($this->entete['CHPSPECCLT'])) {
            if ($initDelaiLiv || $article['DELAI'] != 0) {
                $dteLivr = date('Ymd');
            } else {
                $dteLivr = '00000000';
            }
        } else {
            if ($initDelaiLiv || $article['DELAI'] != '0') {
                $dteLivr = OutilPanierService::getDateLivraisonMin($article['DELAI'], $traitementDA);
            } else {
                $dteLivr = '00000000';
            }
        }

        if ($dteLivr == "00000000" || $dteLivr == '') {
            $dteLivr = $this->rechDatLiv($article['COD_FOURN']);
        }

        $tva = $this->calculTauxTvaService->getTauxTva(
            $article['COD_ART'],
            $article['COD_SFAM'],
            $article['COD_FOURN']??'',
            $centreLivraison,
            $article['TAUX_TVA']??null
        );

        $liste_caract_art = $this->OutilPanierService->initAllCaractArt($article, 0, $article['is_multi_frs']??0, 0);

        if (sql::paravrac($this->pdo, 'OXAPROC', 'MASQUER_BUDGET_SAISIE_LIGNE') == 'O') {
            $arrayCompl['budget_tot'] = 0;
        }

        if (mb_strlen($article['DES_ART']) > 60) {
            $article['DES_COMP'] = $article['DES_ART'].' '.($article['DES_COMP']??'');
        }
        $article['DES_ART']  = mb_substr($article['DES_ART'], 0, 60);
        $article['DES_COMP'] = mb_substr($article['DES_COMP']??'', 0, 3000);

        $oxaUserPanierLigne = new OxaUserPanierLigne($this->pdo);
        $insertLigne = [
            'id_user'               => $idUser,
            'id_panier'             => $idPanier,
            'type_de_ligne'         => intval($type_de_ligne),
            'qte'                   => Outils::qteByUnite($this->pdo, $qte, $article['COD_UNIT']??''),
            'CODE_FM'               => '',
            'CODE_MET'              => $codeMet,
            'CODE_SPE'              => $codeSpe,
            'CodeCtrLivraison'      => $centreLivraison,
            'CHPSPEC01'             => '',
            'PROVENANCE'            => $article['PROVENANCE']??'',
            'ID_CAT'                => $article['ID_CAT']??'',
            'COD_ART'               => $article['COD_ART']??'',
            'COD_FOURN'             => $article['COD_FOURN']??'',
            'RS_FOURN'              => $article['RS_FOURN']??'',
            'REF_FOURN'             => $article['REF_FOURN']??'',
            'REF_FOURN_2'           => $article['REF_FOURN_2']??'',//??
            'COD_FAB'               => $article['COD_FAB']??'',
            'RS_FAB'                => $article['RS_FAB']??'',
            'COD_GAM'               => $article['COD_GAM']??'',
            'LIB_GAM'               => $article['LIB_GAM']??'',
            'REF_FAB'               => $article['REF_FAB']??'',
            'COD_SFAM'              => $article['COD_SFAM']??'',
            'LIB_SFAM'              => mb_substr($article['LIB_SFAM']??'', 0, 30),
            'DES_ART'               => $article['DES_ART'],
            'DES_COMP'              => $article['DES_COMP'],
            'COD_UNIT'              => $article['COD_UNIT']??'',
            'PX_ART'                => $article['PX_ART']??'0',
            'TAUX_TVA'              => $tva,
            'DELAI'                 => $article['DELAI'],
            'CARACT'                => $article['CARACT']??'',
            'IMGART'                => strlen(($article['IMGART']??''))>=200? '':($article['IMGART']??''),
            'TYPIMAGE'              => $article['TYPIMAGE']??'',
            'COD_ACD'               => $article['COD_ACD']??'',
            'COD_GRP'               => $article['COD_GRP']??'',
            'flg_oxaproc_art'       => $type_de_ligne > 0 ? '0' : '1',
            'flg_oxaproc_frs'       => '0',
            'numerique_flg_ligne_ok'=> '0x54',
            'CONDITNT'              => $article['CONDITNT']??'1',
            'TXTCOND'               => $article['TXTCOND']??'',
            'CLASSNUM'              => $article['CLASSNUM']??'',
            'COEFCONV'              => ($article['COEFCONV']??'')==''? '0':$article['COEFCONV'],
            'REFLMAN'               => $REFLMAN,
            'SI_CODE'               => $si??'',
            'CG_CODE'               => $cg??'',
            'CDC_CODE'              => $cdc??'',
            'SCA_CODE'              => $sca??'',
            'NO_CDE'                => $noCde,
            'DATELIVR'              => $dteLivr,
            'MODE_TRS'              => $modTransport,
            'budget_tot'            => $arrayCompl['budget_tot']??'0', // ligne libre
            'OLD_ID_LIG'            => intval($article['id_lig'] ?? 0), // aura une utilité pour d'autre cas ?!
            'CARACT_ART_HAP'        => $liste_caract_art,
            'NO_LIGNE_CA'           => '0',
            'COD_UNIT_PO'           => $article['COD_UNIT_PO']??'', // pour les punchout
            'COD_SFAM_PO'           => $article['COD_SFAM_PO']??'', // pour les punchout
            'FICHTECH'              => ($article['FICHTECH']??null)? 1:0,
            'ARTASSOCIE'            => ($article['ARTASSOCIE']??null)? 1:0,
            'numerique_ASS_OBLIG'   => sql::setBoolSql($articleObligatoire),
            'PRIXDEGRESSIF'         => ($article['PRIXDEGRESSIF']??null)? 1:0,
            'ID_LIGNE_ASSOC'        => $article['ID_LIGNE_ASSOC']??'0',
            'CATPRLST'              => $article['CATPRLST']??'',
            'IDLIGNECAT'            => $article['IDLIGNE']??'0',
            'PX_ART_INIT'           => $article['PX_ART_INIT'],
            'COD_DEV'               => $article['DEVISE']??'',
            'CRITERE_REGROUP'       => $critereArticle,
            'FIN_DEB_PER'           => $FIN_DEB_PER,
            'OUPL_RECEPAUTO_JOUR'   => $RECEPAUTO_JOUR,
            'ID_EXTERNE'            => $article['ID_EXTERNE']??'', // pour les punchout
            'DATEDEBCONT'           => $DATEDEBCONT,
            'DATEFINCONT'           => $DATEFINCONT,
            'PER_REC_AUTO'          => $article['RECEP_AUTO']? ($periodicite??'M'):'',
            'numerique_RECEP_AUTO'  => Sql::setBoolSql($article['RECEP_AUTO']),
        ];
        
        $oxaUserPanierLigne->insert($insertLigne);
        
        $idLignePanier = $this->panierLigne->getLastIdCreate();
        //CritereRegroupService::recalculCritereRegroup($this->pdo, $_SESSION['id_panier'], $idLignePanier);

        //si on est en mode chargement d'un panier modèle ou panier brouillon
        //on ne fais pas l'init des des cc/cs/articles associes
        if ($chargerPanier) {
            return $idLignePanier;
        }
        
        $result     = $this->calculePrixUnite($article, $article['PX_ART']??0, (float)$tva, $this->affichageTVA, $this->decimalPU);
        $unite      = $result['unite'];
        $qteCond    = $result['qteCond'];

        $this->addListeArtEdit($qte, $idLignePanier, ($article['ROW_COMPTEUR']??''), (float)$article['PX_ART'], $qteCond, (float)$tva, $article['DEVISE'], $article['COD_UNIT'], $unite);

        if (/*($article['ARTASSOCIE']??false) &&*/ $modeFils == false && ($type_de_ligne == 0 || $type_de_ligne == 1)) {
            $this->generateArticleAssocier($article, $idLignePanier, $qte, $dteLivr);
        }

        if ($initCC) {
            $caracCompl = new CaracCompl($this->pdo, $article['COD_ART']??'', ($article['COD_SFAM']??''), ($article['CODE_FAM']??''));
            $caracCompl->insertCC('PAN', $idPanier, $idLignePanier, $idUser, $listeValueCC);
        }
        
        (new OutilArticleService($this->pdo))->gestionCsPanier($idPanier, $idUser, 'DA_LIGNE', $insertLigne, $idLignePanier, false, $modeImport, $panierEntete['CODE_STE']);

        return $idLignePanier;
    }

    /**
     * Undocumented function
     *
     * @param array<mixed> $article
     * @param string $idLignePanier
     * @param float $qte
     * @param string $dteLivr
     */
    public function generateArticleAssocier($article, $idLignePanier, $qte, $dteLivr) : void
    {
        $articleAssocie = new ArticleAssocie($this->pdo, $this->pdoOxaFT, $idLignePanier);
        $listeArtAssoc = $articleAssocie->rechercheArticleAssoc();
        
        foreach ($listeArtAssoc as $artAssoc) {
            $result = $artAssoc['art'];
            $result['ID_LIGNE_ASSOC'] = $idLignePanier;
            $result['COD_FOURN'] = $article['COD_FOURN'];
            
            if (empty($result['DEVISE']) || $result['DEVISE'] == '') {
                $result['DEVISE'] = $article['DEVISE'];
            }
            
            if ($artAssoc['enr']['COEFF'] == - 1) {
                $qteAss = 1;
            } else {
                $qteAss = $artAssoc['enr']['COEFF'] * $qte;
            }

            $arrayComplAssoc = [
                'SI'                    => $this->entete['SI_CODE'],
                'SCA'                   => $this->entete['SCA_CODE'],
                'CDC'                   => $this->entete['CDC_CODE'],
                'CG'                    => $this->entete['CG_CODE'],
                'dteLivr'               => $dteLivr,
                'articleObligatoire'    => Sql::boolSql($artAssoc['enr']['OBLIG']),
            ];

            $this->addPanier($result, $qteAss, $arrayComplAssoc, true);
        }
    }

    /**
     * @param array<mixed> $artPanier
     */
    public function deleteLignepanier($artPanier) : void
    {
        $idLigne =  $artPanier['id_lig'];

        $ccLdoc = new CCLDoc($this->pdo);
        $ccLdoc->delete([
            'DOC_TYPE' => 'PAN',
            'ID_USER_BASKET' => $_SESSION['id_user'],
            'DOC_NUM' => $_SESSION['id_panier'],
            'DOC_LINE_NUM' => $idLigne
        ]);

        $oxaUserPanierCsDon = new OxaUserPanierCsDon($this->pdo);
        $oxaUserPanierCsDon->delete([
            'id_user' => $_SESSION['id_user'],
            'id_panier' => $_SESSION['id_panier'],
            'ID_LIGNE' => $idLigne,
        ]);

        $oxaUserPanierLigne = new OxaUserPanierLigne($this->pdo);
        $oxaUserPanierLigne->delete([
            'id_user' => $_SESSION['id_user'],
            'id_panier' => $_SESSION['id_panier'],
            'id_lig'    => $idLigne,
        ]);

        //encore utilisé ?
        $oxaUserPanierLigneFour = new OxaUserPanierLigneFour($this->pdo);
        $oxaUserPanierLigneFour->delete([
            'id_user' => $_SESSION['id_user'],
            'id_panier' => $_SESSION['id_panier'],
            'id_lig'    => $idLigne,
        ]);

        $panierFrs = new PanierFrs($this->pdo);
        $panierFrs->deleteGroupWithNoLine();
        
        $this->addListeArtEdit(0, $idLigne);
    }

    /**
     * @param array<mixed> $infoLigne
     */
    public function updateQteArticle(array $infoLigne, float $qteSaisie) : void
    {
        $requeteArticle = new RequeteArticle($this->pdo, $this->pdoOxaFT);
        $prixArt = $requeteArticle->getPrixDegressifByQte($infoLigne, $qteSaisie);

        $oxaUserPanierLigne = new OxaUserPanierLigne($this->pdo);
        $oxaUserPanierLigne->update([
            'qte'       => Outils::qteByUnite($this->pdo, $qteSaisie, $infoLigne['COD_UNIT']??''),
            'PX_ART'    => $prixArt,
        ], [
            'id_user'   => $_SESSION['id_user'],
            'id_panier' => $_SESSION['id_panier'],
            'id_lig'    => $infoLigne['id_lig'],
        ]);

        $result = $this->calculePrixUnite($infoLigne, $prixArt??0, $infoLigne['TAUX_TVA'], $this->affichageTVA, $this->decimalPU);
        $unite      = $result['unite'];
        $qteCond    = $result['qteCond'];

        $caracCompl = new CaracCompl($this->pdo);
        $caracCompl->updateCalculatedCc(
            ['PU', 'MNT_LIG_HT', 'MNT_LIG_TTC'],
            'PAN',
            $_SESSION['id_panier'],
            $infoLigne['id_lig'],
            $_SESSION['id_user'],
            '',
            false,
            ''
        );

        $this->addListeArtEdit($qteSaisie, $infoLigne['id_lig'], '', $prixArt, $qteCond, $infoLigne['TAUX_TVA'], $infoLigne['COD_DEV'], $infoLigne['COD_UNIT'], $unite);

        if ($infoLigne['ARTASSOCIE']) {
            $this->updateArticleAssoc($infoLigne['id_lig'], $qteSaisie, $infoLigne['qte']);
        }
    }

    /**
     * @param array<mixed> $infoLigne
     * @return array<mixed>
     */
    public static function calculePrixUnite($infoLigne, float $prixArt, float $tva, bool $affichageTVA, int $decimalPU)
    {
        $qteCond = 1;
        if ($infoLigne['TXTCOND'] && (float)$infoLigne['CONDITNT'] == 0) {
            $unite = $infoLigne['TXTCOND'];
        } elseif ($infoLigne['TXTCOND'] == '' && $infoLigne['CONDITNT'] > 1) {
            $prixTvaCond = $prixArt * (1 + $tva / 100);
            $prixCond = ($affichageTVA? $prixTvaCond:$prixArt);

            $unite = $infoLigne['CONDITNT'].' '.$infoLigne['COD_UNIT']. ' à ('.number_format((float)$prixCond, $decimalPU, '.', ' ').' '.$infoLigne['COD_UNIT'].')';

            $qteCond = $infoLigne['CONDITNT'];
        } elseif ($infoLigne['CONDITNT'] > 1) {
            $prixTvaCond = $prixArt * (1 + $tva / 100);
            $prixCond = ($affichageTVA? $prixTvaCond:$prixArt);

            $unite = $infoLigne['TXTCOND'].' de '.number_format($infoLigne['CONDITNT'], 2, '.', ' ').' '.$infoLigne['COD_UNIT'].' à ('.number_format((float)$prixCond, $decimalPU, '.', ' ').' '.$infoLigne['COD_UNIT'].')';
            $qteCond = $infoLigne['CONDITNT'];
        } else {
            $unite = $infoLigne['COD_UNIT'];
        }

        return [
            'unite'     => $unite,
            'qteCond'   => $qteCond,
        ];
    }

    /**
     * @param int $idLigne
     * @param float $newQte
     * @param float $oldQte
     */
    public function updateArticleAssoc($idLigne, $newQte, $oldQte) : void
    {
        if ($newQte>$oldQte) {
            $diffQte = $newQte-$oldQte;
        } else {
            $diffQte = $oldQte-$newQte;
        }

        $artAssocierService = new ArticleAssocie($this->pdo, $this->pdoOxaFT, $idLigne);
        $listeArtAssoc = $artAssocierService->rechercheArticleAssoc();

        $oxaUserPanierLigne = new OxaUserPanierLigne($this->pdo);
        
        foreach ($listeArtAssoc as $artAssoc) {
            $infoLignePanier = $oxaUserPanierLigne->findAll([
                'id_user'           => $_SESSION['id_user'],
                'id_panier'         => $_SESSION['id_panier'],
                'ID_LIGNE_ASSOC'    => $idLigne,

                'COD_ART'           => $artAssoc['art']['COD_ART'],
                'COD_ACD'           => $artAssoc['art']['COD_ACD'],
            ]);

            foreach ($infoLignePanier as $artPanier) {
                panierLigne::majForPanier($artPanier);

                if ($artAssoc['enr']['COEFF'] != - 1) {
                    if ($newQte>$oldQte) {
                        $qteMaj = ($artPanier['qte'] + $diffQte * $artAssoc['enr']['COEFF']);
                    } else {
                        $qteMaj = ($artPanier['qte'] - $diffQte * $artAssoc['enr']['COEFF']);
                    }

                    if ($qteMaj < 0) {
                        $qteMaj = 0;
                    }

                    if ($qteMaj) {
                        $this->updateQteArticle($artPanier, $qteMaj);
                    } else {
                        $this->deleteLignepanier($artPanier);
                    }
                }
            }
        }
    }

    /**
     * @param array<mixed> $arrayLigne
     * @return void
     */
    public function duplicateLigne($arrayLigne = [], bool $dateLigne = false):void
    {
        $idNewLigne = $this->panierLigne->reqDuplicateLigne($arrayLigne, $dateLigne);
        $this->panierLigne->reqDuplicateCsLigne($arrayLigne+[
            'newLigne' => $idNewLigne
        ]);

        $idUser         = $arrayLigne['idUser'];
        $idPanier       = $arrayLigne['idPanier'];
        $idLigne        = $arrayLigne['idLigne'];

        $idUserCible    = $arrayLigne['idUserCible']??null;
        $idPanierCible  = $arrayLigne['idPanierCible']??null;

        $caracCompl = new CaracCompl($this->pdo);
        $caracCompl->duplicateCC(
            'PAN',
            ($idPanierCible? $idPanierCible:$idPanier),
            $idNewLigne,
            ($idUserCible? $idUserCible:$idUser),
            'PAN',
            $idPanier,
            $idLigne,
            $idUser
        );
    }

    public function calculFraisDePort(string $context = null, string $critere = null, string $codeFou = null):bool
    {
        $changementFraisPort = false;
        if ($this->entete['CHIF_EXEC'] == 'E' || $this->entete['ORIGINE'] == 'CreationAvenant') {
            $listeBloc = (new PanierFrs($this->pdo))->getBlocFrsWithFraisPort($critere, $codeFou);
            
            if ($listeBloc) {
                foreach ($listeBloc as $bloc) {
                    if (sql::boolSql($bloc['AUTOCC'])
                        && $bloc['ARTFRPORT'] != ''
                        && (sql::boolSql($bloc['RFRACT']) == false || ($bloc['TOTAL'] < $bloc['MNTMINFRA']))
                        && $bloc['NB_LIGNE'] > 0
                    ) {
                    } else {
                        (new OxaUserPanierLigne($this->pdo))->delete([
                            'id_user' => $_SESSION['id_user'],
                            'id_panier' => $_SESSION['id_panier'],
                            'CRITERE_REGROUP' => $bloc['CRITERE_REGROUP'],
                            'type_de_ligne' => '3'
                        ]);

                        if ($bloc['id_lig']) {
                            $changementFraisPort = true;
                        }
                        continue;
                    }

                    if ($bloc['artPresent']) {
                        if ($bloc['type_de_ligne'] != '3') {
                            (new OxaUserPanierLigne($this->pdo))->update([
                                'type_de_ligne' => 3
                            ], $bloc['id_lig']);
                        }

                        if ($bloc['qte'] == '0') {
                            (new OxaUserPanierLigne($this->pdo))->update([
                                'qte' => 1
                            ], $bloc['id_lig']);
                        }

                        $changementFraisPort = true;
                        continue;
                    }

                    $article['COD_ART'] = $bloc['ARTFRPORT'];
                    $article['COD_FAB'] = '';
                    $article['REF_FOURN'] = '';

                    $articleService = new RequeteArticle($this->pdo, $this->pdoOxaFT);
                    $artFourn = $articleService->infortArt($article, $bloc['COD_FOURN']);

                    if ($artFourn) {
                        $critere = explode('|', $bloc['CRITERE_REGROUP']);
                        
                        if ($artFourn['DEVISE'] != $critere[1]) {
                            //recalcul montant ligne
                            $convertionDevise = new ConvertionDeviseService($this->pdo);

                            $artFourn['PX_ART'] = $artFourn['PX_ART'] * $convertionDevise->getTauxConvDevSrcToDevDest($artFourn['DEVISE'], $critere[1]);
                            $artFourn['PX_ART_INIT'] = $artFourn['PX_ART_INIT'] * $convertionDevise->getTauxConvDevSrcToDevDest($artFourn['DEVISE'], $critere[1]);
                            $artFourn['DEVISE'] = $critere[1];
                            // $artFourn['COD_DEV'] = $critere[1];
                        }
                        
                        $artFourn['type_de_ligne'] = '3';
                        $panierLigneService = new PanierLigneService($this->pdo, $this->pdoOxaFT, 'panier');
                        $idligne = $panierLigneService->addPanier($artFourn, 1, [
                            'centreLivraisonLigne' => $critere[2],
                        ], false, false, [], true);

                        $changementFraisPort = true;
                    } else {
                        $this->listeErrorFraisPort[$bloc['CRITERE_REGROUP']][] = $bloc['ARTFRPORT'];
                    }
                }
            }
        } else {
            (new OxaUserPanierLigne($this->pdo))->delete([
                'id_user' => $_SESSION['id_user'],
                'id_panier' => $_SESSION['id_panier'],
                'type_de_ligne' => '3'
            ]);
            
            if ($context != 'qteChange') {
                $changementFraisPort = true;
            }
        }

        if ($changementFraisPort) {
            (new PanierFrs($this->pdo))->deleteGroupWithNoLine();
        }
        
        return $changementFraisPort;
    }


    //______________ SUB FUNCTION
    private function rechDatLiv(string $codeFourn = null) : string
    {
        if (!$codeFourn) {
            return '00000000';
        }
        if ($_SESSION['sys_panier'] == 'SYS') {
            $result = $this->panierLigne->getDateLigneFrs($codeFourn);
        
            if ($result) {
                $dt_liv = $result['DATELIVR'];
            } else {
                $dt_liv = '00000000';
            }
        } else {
            $dt_liv = '00000000';
        }
        
        return $dt_liv;
    }
}
