<?php

namespace Modules\DemandeAchat\Validator;

use Entity\Model\Acccadre;
use Entity\Model\Articles;
use Entity\Model\Centre;
use Entity\Model\Codecomp;
use Entity\Model\Codgest;
use Entity\Model\DaEntet;
use Entity\Model\DaLigne;
use Entity\Model\Devise;
use Entity\Model\Fourniss;
use Entity\Model\Parametr;
use Entity\Model\Paramnum;
use Entity\Model\Paravrac;
use Entity\Model\Sectimpu;
use Entity\Model\Sscptana;
use GuzzleHttp\Psr7\Response;
use Helpers\ChampsSupplementaire\ChampSupp;
use Helpers\Outil\Date;
use Helpers\Outil\Roles;
use Helpers\Outil\Sql;
use Helpers\Parametres\Constante;
use Helpers\Trad\ITrad;
use Helpers\Trad\Trad;
use Helpers\Validator\Validator;
use Modules\Commande\Service\CalculPlanningService;
use Modules\DemandeAchat\Outil\FormArray;
use Modules\DemandeAchat\Repository\CreationDemandeAchat;
use Modules\DemandeAchat\Repository\ModificationDemandeAchat;
use Modules\DemandeAchat\Service\CreationDemandeAchatService;
use Modules\DemandeAchat\Service\GestionDemandeAchatService;
use Modules\DemandeAchat\Service\ModificationDemandeAchatService;
use Modules\GlobalApplication\Outil\ConversionQteUnite;
use Modules\GlobalApplication\Repository\LicenceOxalys;
use Traits\Validator\Zoom;

class CreationValidator extends Validator
{
    /**
     * validateCreateFormEntet
     *
     * @param  string $purchaseRequestId
     * @param  array<mixed> $post
     * @return bool
     */
    public function validateCreateFormEntet(string $purchaseRequestId, array $post): bool
    {
        // paramètre qui définit si le n° de la DA peut être saisi manuellement ('M'), s'il est donné automatiquement ('A') ou indifférent ('I')
        $params['SECTNUMDA'] = Roles::droit($this->pdo, 'SECTNUMDA');
        $paramNum = new Paramnum($this->pdo);
        if ($params['SECTNUMDA'] == 'O') {
            $paramnum = $paramNum->getNodeNum('DA', $post['CODE_STE'] ?? $_SESSION['Session_SocUsr']);
        } else {
            $paramnum = $paramNum->getNodeNum('DA');
        }

        $formArray = FormArray::getFormArrays($this->trad);

        // s'il peut être saisi, on vérifie qu'il n'est pas déjà attribué, et qu'il s'agit bien d'un integer
        if (($paramnum == 'M' || $paramnum == 'I')) {
            if ($this->isInteger($this->trad->t("Numéro DA"), $post['NO_DA'], ($paramnum == 'M' ? 1 : 0), 9)) {
                $this->isTrue(
                    is_array(
                        (new DaEntet($this->pdo))->find($post['NO_DA'])
                    ),
                    '<br />' . $this->trad->t('Le numéro de DA saisi existe déjà.')
                );
            }
        }

        $this->societeZoom(
            $post['CODE_STE'],
            $this->trad->t('Société'),
            $this->pdo,
            false
        );

        $this->zoom(
            'TypeDoc',
            $post['TYP_DOC'],
            $this->trad->t('Type de document'),
            $this->pdo
        );

        $this->contentInArray(
            $this->trad->t('Chiffrage/Exécution'),
            $post['CHIF_EXEC'],
            $formArray['typeChiffExec']
        );

        $this->validateFormEntet(['CHIF_EXEC' => $post['CHIF_EXEC']], $post);

        return $this->isValid();
    }

    /**
     * validateEditFormEntet
     *
     * @param  string $purchaseRequestId
     * @param  array<mixed> $post
     * @return bool
     */
    public function validateEditFormEntet(string $purchaseRequestId, array &$post): bool
    {
        $heading = (new DaEntet($this->pdo))
            ->find([
                'NO_DA' => $purchaseRequestId,
                'CODE_STE' => $post['CODE_STE']
            ]);

        $this->validateFormEntet($heading, $post);

        $this->zoom('Devise', $post['DEVISE'], $this->trad->t('Détails : Devise'), $this->pdo);
        $this->isFloat($this->trad->t('Détails : Budget'), $post['BUDGETDA'], Constante::formatMontant);

        // supplier data
        $this->zoom('Pays', $post['PAYSFOU'], $this->trad->t('Fournisseur : Pays'), $this->pdo, true);
        $this->isStringAvecEspace($this->trad->t('Fournisseur : Adresse'), $post['ADRFOU'], 0, 90);
        $this->isCodePostal($this->trad->t('Fournisseur : Code Postal'), $post['CPFOU'], $post['PAYSFOU']);
        $this->isStringAvecEspace($this->trad->t('Fournisseur : Ville'), $post['VILLEFOU'], 0, 35);
        $this->isStringAvecEspace($this->trad->t('Fournisseur : Contact'), $post['CTCT_FOU'], 0, 25);
        $this->adresseMail(
            $this->trad->t('Fournisseur : Email'),
            $post['EMA_CTCT'],
            0,
            100
        );
        $this->isStringAvecEspace($this->trad->t('Fournisseur : Téléphone'), $post['TEL_CTCT'], 0, 16);
        $this->isStringAvecEspace($this->trad->t('Fournisseur : Portable'), $post['POR_CTCT'], 0, 16);
        $this->isStringAvecEspace($this->trad->t('Fournisseur : Fax'), $post['FAX_CTCT'], 0, 16);

        /* Info */
        $this->isStringAvecEspace($this->trad->t('Info : Objet'), $post['OBJET_DA'], 0, 60);
        $this->isStringAvecEspace($this->trad->t('Info : Commentaire'), $post['COMMENTAIRE'], 0, 3000);
        $this->isStringAvecEspace($this->trad->t('Info : Titre'), $post['TITRE'], 0, 3000);

        // delivery data
        $this->zoom('Pays', $post['PAYSLIV'], $this->trad->t('Livraison : Pays'), $this->pdo, true);
        $this->isStringAvecEspace($this->trad->t('Livraison : Adresse'), $post['ADRLIV'], 0, 90);
        $this->isCodePostal($this->trad->t('Livraison : Code Postal'), $post['CPLIV'], $post['PAYSLIV']);
        $this->isStringAvecEspace($this->trad->t('Livraison : Ville'), $post['VILLELIV'], 0, 35);
        $this->isStringAvecEspace($this->trad->t('Livraison : Contact'), $post['NMCTC1L'], 0, 25);
        $this->isStringAvecEspace($this->trad->t('Livraison : Fonction'), $post['FTCTC1L'], 0, 25);
        $this->adresseMail(
            $this->trad->t('Livraison : Email'),
            $post['MLCTC1L'],
            0,
            100
        );
        $this->isStringAvecEspace($this->trad->t('Livraison : Téléphone'), $post['TLCTC1L'], 0, 16);
        $this->isStringAvecEspace($this->trad->t('Livraison : Portable'), $post['PRCTC1L'], 0, 16);
        $this->isStringAvecEspace($this->trad->t('Livraison : Fax'), $post['FXCTC1L'], 0, 16);

        /* Cond. Part. */
        /* affichage Centre émetteur */
        $labelCondPart = $this->trad->t('Cond. Part.') . $this->trad->colon();
        $this->zoom('CondPaie', $post['COND_PAIE'], $labelCondPart . $this->trad->t('Condition de paiement'), $this->pdo, true);
        $this->zoom('Modepaie', $post['MODE_PAIE'], $labelCondPart . $this->trad->t('Mode de paiement'), $this->pdo, true);
        $this->zoom('Modelivr', $post['MODE_LIV'], $labelCondPart . $this->trad->t('Mode de livraison'), $this->pdo, true);
        $this->isDate($post['DTE_LIV'], '', '', true, $labelCondPart . $this->trad->t('Date de livraison'));
        $this->zoom('Messstan', $post['CODE_MESS'], $labelCondPart . $this->trad->t('Message'), $this->pdo, true);

        /* CS */
        $idDaCS = ChampSupp::encodeCodeEnr('DA_ENTET', $purchaseRequestId);
        // $this->validatorCS('CA_ENTET', $idDaCS, $post, $this->pdo);
        $this->validatorCS('DA_ENTET', $idDaCS, $post, $this->pdo);

        return $this->isValid();
    }

    /**
     * validateFormEntet
     *
     * @param  array<mixed> $heading
     * @param  array<mixed> $post
     * @return void
     */
    public function validateFormEntet(array $heading, array $post): void
    {
        $trad = $this->getTrad();
        $transport = (new CreationDemandeAchatService($this->pdo, $trad))
            ->getTransportOptions();

        $tabTypeMarchePublic = [
            'C' => $trad->t('Continu'),
            'R' => $trad->t('Récurrent'),
            'U' => $trad->t('Unique')
        ];

        $configAxeImp = (new Paravrac($this->pdo))
            ->getDemandeAxeImpConfig($post['CODE_STE']);
        $parameters = new Parametr($this->pdo);

        /*** VALIDATION DE l'ENTETE DE LA DA ***/
        /* Détails */
        $this->demandeurZoom(
            $post['NO_DEM'],
            $trad->t('Détails : Demandeur'),
            $this->pdo,
            false,
            ['CODE_STE' => $post['CODE_STE']]
        );

        //___________________
        // Imputation
        // TODO : factorize

        $dateRefValid = $heading['DTE_EMISS'] ?? date('Ymd');

        if ($configAxeImp->SectImp->isActive) {
            $this->zoom(
                'Sectimpu',
                $post['SECTIMP'],
                $trad->t('Détails : Section d\'imputation'),
                $this->pdo,
                true,
                ($configAxeImp->SectImp->isSecto ?
                    ['CODE_STE' => $post['CODE_STE']] : [])
            );


            $sectionImp = (new Sectimpu($this->pdo))->find(
                ['CODE_SI' => $post['SECTIMP']] + ($configAxeImp->SectImp->isSecto ? ['CODE_STE' => $post['CODE_STE']] : [])
            );

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

            // Validate SectImpu date
            if ($sectionImp != null) {
                $this->entityDateValidation(
                    DaEntet::class,
                    Sectimpu::class,
                    $trad,
                    $sectionImp['DATE_DEB'],
                    $sectionImp['DATE_FIN'],
                    $dateRefValid
                );
            }

            // Case : SectImp can have a CodeGest
            if (isset($sectionImp) && $sectionImp['SICODG']) {
                $this->codeGestionZoom(
                    $post['CODGES'],
                    $trad->t('Code gestion'),
                    $this->pdo,
                    !Sql::toBool($sectionImp['IMPCODG']),
                    [
                        'CODE_STE' => $post['CODE_STE'],
                        'CODE_SI' => $sectionImp['CODE_SI'],
                        'AUTHACHAT' => 1,
                        'valide_obligatoire' => 1,
                        'cgParId' => Roles::droit($this->pdo, 'CODE_GESTION_PAR_ID')
                            ? 1
                            : 0
                    ]
                );
            }
        }

        if ($configAxeImp->CodeCompl->isActive) {
            $this->zoom(
                'Codecomp',
                $post['CODECOMP'],
                $trad->t('Détails : Code complémentaire'),
                $this->pdo,
                true,
                ($configAxeImp->CodeCompl->isSecto ?
                    ['CODE_STE' => $post['CODE_STE']] : [])
            );

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

            if ($codeComp != null) {
                $this->entityDateValidation(
                    DaEntet::class,
                    Codecomp::class,
                    $trad,
                    $codeComp['DATE_DEB'],
                    $codeComp['DATE_FIN'],
                    $dateRefValid
                );
            }
        }

        if ($configAxeImp->SousCompteAna->isActive) {
            $this->zoom(
                'Sscptana',
                $post['SSCPTEANA'],
                $trad->t('Détails : Sous compte d\'analyse'),
                $this->pdo,
                true,
                ($configAxeImp->SousCompteAna->isSecto ?
                    ['CODE_STE' => $post['CODE_STE']] : [])
            );

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

            if ($sousComptAna != null) {
                $this->entityDateValidation(
                    DaEntet::class,
                    Sscptana::class,
                    $trad,
                    $sousComptAna['DATE_MINI'],
                    $sousComptAna['DATE_MAXI'],
                    $dateRefValid
                );
            }
        }

        //___________________

        if (Sql::boolSql(Sql::paravrac($this->pdo, 'PARAMGEN', 'CTRLSEUILPARSFA'))) {
            $this->contentInArray($trad->t('Détails : Type d\'achat'), $post['TYPNMP'], $tabTypeMarchePublic);
        }
        $this->isStringAvecEspace($trad->t('Détails : Zone libre DA'), $post['ZONELIB'], 0, 30);

        if (Sql::boolSql(sql::paravrac($this->pdo, 'PARAMOXA', 'MULTILNGACTIF'))) {
            $this->zoom('Langues', $post['COD_LNG'], $trad->t('Détails : Langue de la DA'), $this->pdo);
        }

        /* Fournisseur */
        $this->accordCadreZoom(
            $post['ACD'],
            $trad->t('Fournisseur : Accord-cadre'),
            $this->pdo,
            true,
            [
                'CODE_STE' => $post['CODE_STE'],
                'CENTRE_EMETTEUR' => $post['DAENT_CENTRE_EMETTEUR'],
                'CENTRE_LIVRAISON' => $post['CTR_LIV'],
                'FS_ACD_EXISTE' => '1',
                'TYPE_FRS' => ($heading['CHIF_EXEC'] == 'E' ? 'F' : '')
            ]
        );

        if ($post['ACD'] != '') {
            if ($this->isTrue(
                $post['FOU'] == '',
                '<br />' . $trad->t('Fournisseur : Le code fournisseur ne peut être vide en présence d\'un accord-cadre.')
            )) {
                $acd = (new Acccadre($this->pdo))
                    ->find($post['ACD']);

                if ($acd['TYPE_FG'] == 'F'
                    && $this->isFalse(
                        $post['FOU'] == $acd['CODE_FOUR'],
                        Trad::strBuild(
                            $trad->t('Fournisseur : Le code fournisseur @1@ ne correspond pas au code fournisseur de l\'accord-cadre @2@.'),
                            $post['FOU'],
                            $post['ACD']
                        )
                    )
                ) {
                    $this->fournisseurZoom(
                        $post['FOU'],
                        $trad->t('Fournisseurs de l\'accord-cadre'),
                        $this->pdo,
                        false,
                        [
                            'valide' => 1,
                            'filter_egal_PROSPECT' => ($heading['CHIF_EXEC'] == 'E' ? 'F' : '')
                        ]
                    );
                } else {
                    $this->fournisseurZoom(
                        $post['FOU'],
                        $trad->t('Fournisseurs de l\'accord-cadre'),
                        $this->pdo,
                        false,
                        [
                            'ACD_FG' => $post['ACD'],
                            'valide' => 1,
                            'filter_egal_PROSPECT' => ($heading['CHIF_EXEC'] == 'E' ? 'F' : '')
                        ]
                    );
                }
            }
        } else {
            $this->fournisseurZoom(
                $post['FOU'],
                $trad->t('Fournisseur : Fournisseur'),
                $this->pdo,
                true,
                [
                    'valide' => 1,
                    'filter_egal_PROSPECT' => ($heading['CHIF_EXEC'] == 'E' ? 'F' : '')
                ]
            );
        }

        if ((new LicenceOxalys($this->pdo))->noteFourActive()) {
            $this->isCheck($post['NOCDISDA']);
        }

        /* Livraison */
        $this->zoom(
            'Centre',
            $post['CTR_LIV'],
            $trad->t('Livraison : Centre de livraison'),
            $this->pdo,
            false,
            [
                'filter_LIVRAISON' => 'T',
                'filter_egal_CODE_STE' => $post['CODE_STE']
            ]
        );

        if ((new LicenceOxalys($this->pdo))->expeditionActive()) {
            $deliveryCenter = (new Centre($this->pdo))
                ->find($post['CTR_LIV']);
            if (Sql::boolSql($deliveryCenter['TRS_INTER'])) {
                $this->contentInArray(
                    $trad->t('Livraison : Mode de transport'),
                    $post['MOD_TRS'],
                    $transport
                );
            }
        }

        /* affichage Centre émetteur */
        $labelDetails = $trad->t('Détails') . $trad->colon();
        $this->zoom(
            'Centre',
            $post['DAENT_CENTRE_EMETTEUR'],
            $labelDetails . $trad->t('Centre émetteur'),
            $this->pdo,
            false,
            [
                'filter_EMISSION' => 'T',
                'filter_egal_CODE_STE' => $post['CODE_STE']
            ]
        );
    }

    /**
     * validateFormLine
     *
     * @param  string $purchaseRequestId
     * @param  array<mixed> $post
     * @return bool
     */
    public function validateFormLine(string $purchaseRequestId, array &$post): bool
    {
        $trad = $this->getTrad();
        $heading = (new DaEntet($this->pdo))
            ->find([
                'NO_DA' => $purchaseRequestId,
                'CODE_STE' => $post['CODE_STE']
            ]);

        $transport = (new CreationDemandeAchatService($this->pdo, $trad))
            ->getTransportOptions();

        $formArray = FormArray::getFormArrays($this->trad);


        $parameters = (new Parametr($this->pdo))->get();

        $idLigne = $post['LIGNE_NO_PO_MODIF'];

        /*** VALIDATION ***/
        $lineExists = (new DaLigne($this->pdo))
            ->find([
                'NO_DA' => $purchaseRequestId,
                'NO_PO' => $idLigne
            ]);

        if (!$lineExists
            && (new ModificationDemandeAchat($this->pdo))->getNombreLigneDA($purchaseRequestId) >= 999
        ) {
            $this->setError(
                $trad->t("Il n'est pas possible de créer une nouvelle ligne, votre demande d'achat a déjà atteint le nombre maximum de 999 lignes.")
            );
        } else {
            // contrôles fournisseur/accord-cadre
            $this->accordCadreZoom(
                $post['ligne_ACD'],
                $trad->t('Accord-cadre'),
                $this->pdo,
                true,
                [
                    'CODE_STE' => $post['CODE_STE'],
                    'CENTRE_EMETTEUR' => $post['DAENT_CENTRE_EMETTEUR'],
                    'CENTRE_LIVRAISON' => $post['ligne_CTRLIVR'],
                    'FS_ACD_EXISTE' => '1',
                    'TYPE_FRS' => ($heading['CHIF_EXEC'] == 'E' ? 'F' : '')
                ]
            );

            if ($post['ligne_ACD'] != '') {
                if ($this->isTrue(
                    $post['ligne_CODE_FOU'] == '',
                    '<br />' . $trad->t('Le code fournisseur ne peut être vide en présence d\'un accord-cadre.')
                )) {
                    $acd = (new Acccadre($this->pdo))
                        ->find($post['ligne_ACD']);
                    if ($acd['TYPE_FG'] == 'F'
                        && $this->isFalse(
                            $post['ligne_CODE_FOU'] == $acd['CODE_FOUR'],
                            Trad::strBuild(
                                $trad->t('Le code fournisseur @1@ ne correspond pas au code fournisseur de l\'accord-cadre @2@.'),
                                $post['ligne_CODE_FOU'],
                                $post['ligne_ACD']
                            )
                        )
                    ) {
                        $this->fournisseurZoom(
                            $post['ligne_CODE_FOU'],
                            $trad->t('Fournisseur'),
                            $this->pdo,
                            false,
                            [
                                'valide' => 1,
                                'filter_egal_PROSPECT' => ($heading['CHIF_EXEC'] == 'E' ? 'F' : '')
                            ]
                        );
                    } else {
                        $this->fournisseurZoom(
                            $post['ligne_CODE_FOU'],
                            $trad->t('Fournisseur'),
                            $this->pdo,
                            false,
                            [
                                'ACD_FG' => $post['ligne_ACD'],
                                'valide' => 1,
                                'filter_egal_PROSPECT' => ($heading['CHIF_EXEC'] == 'E' ? 'F' : '')
                            ]
                        );
                    }
                }
            } else {
                $this->fournisseurZoom(
                    $post['ligne_CODE_FOU'],
                    $trad->t('Fournisseur'),
                    $this->pdo,
                    true,
                    [
                        'valide' => 1,
                        'filter_egal_PROSPECT' => ($heading['CHIF_EXEC'] == 'E' ? 'F' : '')
                    ]
                );
            }

            // contrôles article
            $this->zoom(
                'Articles',
                $post['ligne_CODE_ART'],
                Trad::strBuild(
                    $trad->t('Ligne @1@ : Article'),
                    $idLigne
                ),
                $this->pdo,
                true
            );

            // si l'article est stocké et pas de stock renseigné => alerte non-bloquante pour confirmer le non-stockage
            $item = (new Articles($this->pdo))
                ->find($post['ligne_CODE_ART']);

            if (Sql::boolSql($item['STOCKE'] ?? false)
                && $post['ligne_SITE_STK'] == ''
                && (new LicenceOxalys($this->pdo))->termPaieActive()
            ) {
                $this->setErrorNonBloquant($trad->t('Pas de site sur article stocké.'));
            }

            // la ligne doit comporter un code article OU une désignation au minimum
            $minDesSomm = $post['ligne_CODE_ART'] == '' ? 1 : 0;
            $this->isStringAvecEspace(
                $trad->t('Désignation Article'),
                $post['ligne_DES_SOMM'],
                $minDesSomm,
                60
            );

            if (Sql::boolSql($parameters->CTRL_QTDA)
                && Sql::boolSql($parameters->SAI_QTEDA)
            ) {
                if (!Sql::boolSql($parameters->BLO_QTEDA) && ($post['ligne_QTE_DEM'] == 0 || $post['ligne_QTE_DEM'] == '')) {
                    $this->setErrorNonBloquant($trad->t('La quantité est nulle.'));
                }
            }

            $qteOK = $this->isFloat(
                $trad->t('Quantité'),
                $post['ligne_QTE_DEM'],
                Constante::formatQTE,
                Sql::boolSql($parameters->BLO_QTEDA)
            );

            $uniteOK = $this->zoom(
                'Unites',
                $post['ligne_UNITE'],
                $trad->t('Unité'),
                $this->pdo
            );

            if ($qteOK
                && $uniteOK
                && $post['ligne_CODE_ART'] != ''
                && $post['ligne_QTE_DEM'] != 0
            ) {
                // Contrôle de la quantité de conditionnement
                // 1/ récupération quantité de conditionnement fournisseur ou groupement fournisseur
                $qteCondFou = (new CreationDemandeAchat($this->pdo))
                    ->getQteCondFou(
                        $post['ligne_CODE_ART'],
                        $post['ligne_CODE_FOU'],
                        (new Fourniss($this->pdo))
                            ->find($post['ligne_CODE_FOU'])['FOURPRIN'] ?? ''
                    )['QTE_COND'];


                // 2/ convertion de la quantité en unité de la DA en quantité en unité de l'article
                $qteConvertie = $post['ligne_QTE_DEM'];
                $uniteArticle = (new Articles($this->pdo))
                    ->find($post['ligne_CODE_ART'])['UNIT'];
                if ($uniteArticle != $post['ligne_UNITE']) {
                    $taux = ConversionQteUnite::getTaux(
                        $this->pdo,
                        [
                            'CODE_ART' => $post['ligne_CODE_ART'],
                            'CODE_UNI2' => $post['ligne_UNITE'],
                        ]
                    );
                    if ($taux == 0) {
                        $this->setErrorNonBloquant($trad->t('Unité non Convertie en Unité de Référence Article.'));
                    } else {
                        $qteConvertie = ConversionQteUnite::getQuantiteConvertie([
                            'QTE' => $post['ligne_QTE_DEM'],
                            'TAUX' => $taux
                        ]);
                    }
                }

                // 3/ vérification de la quantité : doit être multiple de la quantité de conditionnement
                if ((float) $qteCondFou != 0 && (float) $qteConvertie % (float) $qteCondFou !== 0) {
                    $this->setErrorNonBloquant(
                        Trad::strBuild(
                            $trad->t('La quantité @1@ @2@ n\'est pas un multiple de la quantité de conditionnement @3@ @4@.'),
                            $post['ligne_QTE_DEM'],
                            $post['ligne_UNITE'],
                            $qteCondFou,
                            $uniteArticle
                        )
                    );
                }
            }

            if ((Sql::boolSql($parameters->CTRL_PUDA)
                    && Sql::boolSql($parameters->SAI_PUDA)
                    && !Sql::boolSql($parameters->BLO_PUDA))
                && ($post['ligne_PU'] == 0
                    || $post['ligne_PU'] == '')
            ) {
                $this->setErrorNonBloquant($trad->t('Le prix unitaire est nul.'));
            }
            $this->isFloat(
                $trad->t('Prix Unitaire'),
                $post['ligne_PU'],
                Constante::formatPU,
                Sql::boolSql($parameters->CTRL_PUDA)
                    && Sql::boolSql($parameters->BLO_PUDA)
            );

            $this->isFloat(
                $trad->t('Taux de remise'),
                $post['ligne_TX_REMISE'],
                3.2,
                false,
                '100'
            );

            if (array_key_exists('ligne_DEJA_COMM', $post)) {
                $this->isFloat(
                    $trad->t('Quantité déjà commandée'),
                    $post['ligne_DEJA_COMM'],
                    Constante::formatQTE
                );
            }
            if (array_key_exists('ligne_MNT_LIG', $post)) {
                $this->isFloat(
                    $trad->t('Montant HT'),
                    $post['ligne_MNT_LIG'],
                    Constante::formatMontant
                );
            }

            $this->isFloat(
                $trad->t('Budget'),
                $post['ligne_BUDGET'],
                Constante::formatMontant
            );

            if ($recepAuto = $this->isCheck($post['ligne_RECEP_AUTO'])) {
                $this->isDate($post['ligne_DATEDEBCONT'], '', '', false, $trad->t('Début contrat'));
                $this->isDate($post['ligne_DATEFINCONT'], '', '', false, $trad->t('Fin contrat'));
                $this->contentInArray($trad->t('Périodicité du contrat'), $post['ligne_CONTRAT_PERIOD'], $formArray['tabPeriodicite']);
                $this->contentInArray($trad->t('Type de période'), $post['ligne_FIN_DEB_PER'], $formArray['tabPeriode']);
                $this->contentInArray($trad->t('Jour d\'application'), $post['ligne_DALI_RECEPAUTO_JOUR'], $formArray['tabJoursAppli']);
            } else {
                $post['ligne_DATEDEBCONT'] = '00000000';
                $post['ligne_DATEFINCONT'] = '00000000';
                $post['ligne_CONTRAT_PERIOD'] = '';
                $post['ligne_FIN_DEB_PER'] = '';
                $post['ligne_DALI_RECEPAUTO_JOUR'] = '';
            }

            $planning = [];

            if ($post['calculPlanning'] == '1' && $recepAuto) {
                $calculPlanningService = new CalculPlanningService(
                    $post['ligne_QTE_DEM'],
                    ($post['ligne_CONTRAT_PERIOD'] ?? ''),
                    $post['ligne_DATEDEBCONT'],
                    $post['ligne_DATEFINCONT'],
                    ($post['ligne_FIN_DEB_PER'] ?? ''),
                    ($post['ligne_DALI_RECEPAUTO_JOUR'] ?? '')
                );

                $calculPlanningService->calculPlanning('DA');
                $planning = $calculPlanningService->getTableauEcheance();
            }

            // TODO A MODIFIER POUR PRENDRE EN COMPTE LE PLANNING
            // if (Sql::boolSql($parameters->CTRL_DLDA) && Sql::boolSql($parameters->SAI_DLDA)) {
            //     $this->isDate(
            //         $post['ligne_DTELIVSOU'],
            //         '',
            //         '',
            //         !Sql::boolSql($parameters->BLO_DLDA),
            //         $trad->t('Date de livraison')
            //     );

            //     if (!Sql::boolSql($parameters->BLO_DLDA) && $post['ligne_DTELIVSOU'] == '00000000') {
            //         $this->setErrorNonBloquant($trad->t('La date de livraison est nulle.'));
            //     }
            // } else {
            //     $this->isDate(
            //         $post['ligne_DTELIVSOU'],
            //         '',
            //         '',
            //         true,
            //         $trad->t('Date de livraison')
            //     );
            // }

            $countPlanning = 0;
            $totalQTE = 0;
            $dateLivraison = [];
            // foreach ($post as $key => $val) {
            //     if (strpos($key, 'PLANNING-DTE_LIV') === 0) {
            //         $countPlanning++;
            //         $planning[] = [
            //             'DTE_LIV' => Date::dateToSql($val),
            //             'QTE_DEMAN' => $post['PLANNING-QTE_DEMAN-' . substr($key, -1)]
            //         ];

            //         $this->isFloat(
            //             $trad->t('Quantité planning') . ' ' . substr($key, -1),
            //             $post['PLANNING-QTE_DEMAN-' . substr($key, -1)],
            //             Constante::formatQTE,
            //         );

            //         $totalQTE .= $post['PLANNING-QTE_DEMAN-' . substr($key, -1)];
            //     }
            // }

            $accEntity = new Acccadre($this->pdo);
            $infoAcd = $accEntity->find($post['ligne_ACD']);
            if (!empty($planning)) {
                foreach ($planning as $k => $v) {
                    $post['PLANNING-DTE_LIV-' . ($k + 1)] = Date::dateConverte($v['DTE_LIV']);
                    $post['PLANNING-QTE_DEMAN-' . ($k + 1)] = $v['QTE_DEMAN'];
                }
            }

            foreach ($post as $key => $val) {
                if (strpos($key, 'PLANNING-DTE_LIV') === 0) {
                    $explodeKey = explode('-', $key);
                    $planningId = $explodeKey[2];

                    $this->isFloat(
                        $trad->t('Quantité'),
                        $post['PLANNING-QTE_DEMAN-' . $planningId],
                        Constante::formatQTE
                    );
                    $this->DAControleDateLivraison(
                        $post['PLANNING-DTE_LIV-' . $planningId],
                        Trad::strBuild(
                            $trad->t('Date de livraison du planning n°@1@'),
                            $planningId
                        ),
                        true,
                        $infoAcd
                    );
                    if ($post['ligne_DATEDEBCONT'] != '00000000' && $post['ligne_DATEFINCONT'] != '00000000') {
                        $this->between(
                            $post['PLANNING-DTE_LIV-' . $explodeKey[2]],
                            $post['ligne_DATEDEBCONT'],
                            $post['ligne_DATEFINCONT'],
                            $trad->t('Date de livraison')
                        );
                    }

                    if (isset($dateLivraison[$post['PLANNING-DTE_LIV-' . $explodeKey[2]]])) {
                        $this->setError(trad::strBuild(
                            $trad->t('La date @1@ est dupliquée sur le planning.'),
                            Date::dateConverte($post['PLANNING-DTE_LIV-' . $explodeKey[2]])
                        ));
                    }

                    $dateLivraison[$post['PLANNING-DTE_LIV-' . $explodeKey[2]]] = $post['PLANNING-DTE_LIV-' . $explodeKey[2]];
                    $planning[] = [
                        'QTE_DEMAN' => $post['PLANNING-QTE_DEMAN-' . $explodeKey[2]],
                        'DTE_LIV' => $post['PLANNING-DTE_LIV-' . $explodeKey[2]],
                    ];

                    $totalQTE += floatval($post['PLANNING-QTE_DEMAN-' . $explodeKey[2]]);
                }
            }
            // else {
            //     foreach($planning as $key => $value) {
            //         $this->isFloat(
            //             $trad->t('Quantité'),
            //             $value['QTE_DEMAN'],
            //             Constante::formatQTE
            //         );

            //         $value['DTE_LIV'] = Date::dateConverte($value['DTE_LIV']);
            //         $this->DAControleDateLivraison(
            //             $value['DTE_LIV'],
            //             Trad::strBuild(
            //                 $trad->t('Date de livraison du planning n°@1@'),
            //                 $key
            //             ),
            //             true,
            //             $infoAcd
            //         );
            //         if ($post['ligne_DATEDEBCONT'] != '00000000' && $post['ligne_DATEFINCONT'] != '00000000') {
            //             $this->between($value['DTE_LIV'], $post['ligne_DATEDEBCONT'], $post['ligne_DATEFINCONT'], $trad->t('Date de livraison'));
            //         }

            //         if (isset($dateLivraison[$value['DTE_LIV']])) {
            //             $this->setError(trad::strBuild($trad->t('La date @1@ est dupliquée sur le planning.'), Date::dateConverte($post['PLANNING-DTE_LIV-'.$explodeKey[2]])));
            //         }

            //         $dateLivraison[$value['DTE_LIV']] = $value['DTE_LIV'];

            //         $totalQTE += floatval($value['QTE_DEMAN']);
            //     }
            // }

            // on vérifie que la quantité cumulée du planning correspond à la quantité de la ligne
            if (count($planning) > 1) {
                $totalQTE = round($totalQTE, 3);
                $qteLigne = round((float)$post['ligne_QTE_DEM'], 3);
                $this->isTrue($totalQTE != $qteLigne, $trad->t('La somme des quantités du planning est différente de celle de la ligne.'));
            }

            if (count($planning) == 1 && !($post['ligne_RECEP_AUTO'] ?? false)) {
                $this->DAControleDateLivraison(
                    $post['ligne_DTELIVSOU'],
                    $trad->t('Délai'),
                );
            } elseif ($post['calculPlanning'] == '0') {
                Date::dateToSql($post['ligne_DTELIVSOU']);
                $totalQTE = round($totalQTE, 3);
                $qteLigne = round((float)$post['ligne_QTE_DEM'], 3);
                $this->isTrue($totalQTE != $qteLigne, $trad->t('La somme des quantités du planning est différente de celle de la ligne.'));
            } else {
                $post['ligne_DTELIVSOU'] = '00000000';
            }

            /* Détails ligne */
            $this->isStringAvecEspace($trad->t('Désignation complémentaire'), $post['ligne_DESIGNCOMP'], 0, 3000);
            $this->zoom('SousFamille', $post['ligne_SSFAM'], $trad->t('Sous-famille'), $this->pdo);
            $this->zoom('Cqualite', $post['ligne_CTRL_BR'], $trad->t('Contrôle qualité'), $this->pdo, true);
            $this->isStringAvecEspace($trad->t('Référence fournisseur'), $post['ligne_REF_FOUR'], 0, 30);
            $this->zoom('Fabricant', $post['ligne_COD_FAB'], $trad->t('Fabricant'), $this->pdo, true);
            $this->zoom('Gamme', $post['ligne_COD_GAM'], $trad->t('Code gamme'), $this->pdo, true);
            $this->isStringAvecEspace($trad->t('Référence fabricant'), $post['ligne_REF_FAB'], 0, 30);

            //_____________________________
            // Imputation
            // TODO : factorize

            $configAxeImp = (new Paravrac($this->pdo))
                ->getDemandeAxeImpConfig($post['CODE_STE']);
            if ($configAxeImp->SectImp->isActive) {
                $this->zoom(
                    'Sectimpu',
                    $post['ligne_SECTIMP'],
                    $trad->t('Section d’imputation'),
                    $this->pdo,
                    $configAxeImp->SectImp->isBlankAllowed,
                    ($configAxeImp->SectImp->isSecto ?
                        ['CODE_STE' => $post['CODE_STE']] : [])
                );

                $sectionImp = (new Sectimpu($this->pdo))->find(
                    ['CODE_SI' => $post['ligne_SECTIMP']] +
                        ($configAxeImp->SectImp->isSecto ? ['CODE_STE' => $post['CODE_STE']] : [])
                );


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

                // Validate SectImpu date
                if ($sectionImp != null) {
                    $this->entityDateValidation(
                        DaLigne::class,
                        Sectimpu::class,
                        $trad,
                        $sectionImp['DATE_DEB'],
                        $sectionImp['DATE_FIN'],
                        $heading['DTE_EMISS']
                    );
                }

                // Case : SectImp can have a CodeGest
                if (isset($sectionImp) && $sectionImp['SICODG']) {
                    $this->codeGestionZoom(
                        $post['ligne_CODGES'],
                        $trad->t('Code gestion'),
                        $this->pdo,
                        !Sql::toBool($sectionImp['IMPCODG']),
                        [
                            'CODE_STE' => $post['CODE_STE'],
                            'CODE_SI' => $sectionImp['CODE_SI'],
                            'AUTHACHAT' => 1,
                            'valide_obligatoire' => 1,
                            'cgParId' => Roles::droit($this->pdo, 'CODE_GESTION_PAR_ID')
                                ? 1
                                : 0
                        ]
                    );
                }
            }
            if ($configAxeImp->CodeCompl->isActive) {
                $this->zoom(
                    'Codecomp',
                    $post['ligne_CODE_COMP'],
                    $trad->t('Code complémentaire'),
                    $this->pdo,
                    $configAxeImp->CodeCompl->isBlankAllowed,
                    ($configAxeImp->CodeCompl->isSecto ?
                        ['CODE_STE' => $post['CODE_STE']] : [])
                );

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

                if ($codeComp != null) {
                    $this->entityDateValidation(
                        DaLigne::class,
                        Codecomp::class,
                        $trad,
                        $codeComp['DATE_DEB'],
                        $codeComp['DATE_FIN'],
                        $heading['DTE_EMISS']
                    );
                }
            }
            if ($configAxeImp->SousCompteAna->isActive) {
                $this->zoom(
                    'Sscptana',
                    $post['ligne_SSCPTEANA'],
                    $trad->t('Sous compte d\'analyse'),
                    $this->pdo,
                    $configAxeImp->SousCompteAna->isBlankAllowed,
                    ($configAxeImp->SousCompteAna->isSecto ?
                        ['CODE_STE' => $post['CODE_STE']] : [])
                );

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

                if ($sousComptAna != null) {
                    $this->entityDateValidation(
                        DaLigne::class,
                        Sscptana::class,
                        $trad,
                        $sousComptAna['DATE_MINI'],
                        $sousComptAna['DATE_MAXI'],
                        $heading['DTE_EMISS']
                    );
                }
            }

            //___________________________

            $this->zoom('TVA', $post['ligne_TVA'], $trad->t('TVA'), $this->pdo, true);
            $this->zoom(
                'Centre',
                $post['ligne_CTRLIVR'],
                $trad->t('Centre de livraison'),
                $this->pdo,
                true,
                [
                    'filter_egal_LIVRAISON' => 'T',
                    'filter_egal_CODE_STE' => $post['CODE_STE']
                ]
            );


            if ((new LicenceOxalys($this->pdo))->expeditionActive()) {
                $deliveryCenter = (new Centre($this->pdo))->find($post['ligne_CTRLIVR']);
                if (is_array($deliveryCenter)) {
                    if (Sql::boolSql($deliveryCenter['TRS_INTER'])) {
                        $this->contentInArray(
                            $trad->t('Mode de transport'),
                            $post['ligne_MOD_TRS'] ?? '',
                            $transport
                        );
                    }
                }
            }

            if ((new LicenceOxalys($this->pdo))->termPaieActive()) {
                $this->siteStockZoom(
                    $post['ligne_SITE_STK'],
                    $trad->t('Site stock'),
                    true,
                    [
                        'CODE_ART' => $post['ligne_CODE_ART'],
                        'filter_egal_CODE_STE' => $post['CODE_STE'],
                        'date_art_ouvert' => $post['DTE_EMISS']
                    ]
                );
            }


            if (Sql::boolSql(Sql::paravrac($this->pdo, 'PARAMGEN', 'CTRLSEUILPARSFA'))) {
                $this->contentInArray(
                    $trad->t('Type d\'achat'),
                    $post['ligne_TYPNMP'],
                    $formArray['tabTypeMarchePublic']
                );
            }

            $idCSLigne = ChampSupp::autoCompletCodeEnr($purchaseRequestId, $idLigne, 'DA_LIGNE');
            // TODO si ce n'est pas la date du jour à prendre en compte pour la vérification des CS dans TS_DON, quelle date de la DA faut-il prendre ?
            $this->validatorCS('DA_LIGNE', $idCSLigne, $post, $this->pdo, $post['CODE_STE']);
            $this->validatorCC($this->pdo, $post);
        }

        return $this->isValid();
    }
}
