<?php

namespace Traits\Validator;

use Entity\Model\Codecomp;
use Entity\Model\Codgest;
use Entity\Model\Parametr;
use Entity\Model\Sectimpu;
use Entity\Model\SousFamille;
use Entity\Model\Sscptana;
use Entity\Model\SSiteSto;
use Entity\Model\Unites;
use Helpers\Log\LogSysteme;
use Helpers\Outil\Sql;
use Helpers\Outil\ZoomHelper;
use Helpers\Trad\ITrad;
use Helpers\Trad\Trad;
use Modules\Ajax\Repository\Listes;
use PDO;
use Psr\Container\ContainerInterface;

trait Zoom
{
    abstract public function getTrad(): ITrad;
    abstract public function getContainer(): ContainerInterface;

    /**
     *
     * @param mixed $value              : valeur à vérifier
     * @param boolean $null             : null autorisé ou non ? pas autorisé par defaut
     * @param array<mixed> $post               : filtre eventuelle sur l'entity
     * @param string $messageSpecifique : message spéficique
     * @param array<string> $selectTable
     * @return bool
     */
    public function zoom(string $entity, $value, string $nomChamp, \PDO $pdo, $null = false, $post = [], $messageSpecifique = '', $selectTable = []): bool
    {
        if (strtoupper($entity) == 'SOCIETE') {
            return $this->societeZoom($value, $nomChamp, $pdo, $null, $post, $messageSpecifique);
        }

        $test = $entity;
        $value = mb_strtoupper(trim($value));
        if ($value == '' && $null) {
            return true;
        }

        if ((!$value) && !$null) {
            $this->validate += 1;
            $this->error .= '<br />' . Trad::strBuild($this->getTrad()->t('Le champ @1@ ne peut pas être vide.'), $nomChamp);
            return false;
        }

        // TODO : remove dynamic call to class
        $generatorEntity = "\\Entity\\Model\\" . trim($entity);

        /** @var \Helpers\QueryBuilder\QueryBuilder */
        $entityQb = new $generatorEntity($pdo);

        $primaryKey = $entityQb->getPrimaryKey();

        if (isset($this->listeValueEntite[$test]) && in_array($value, $this->listeValueEntite[$test])) {
            return true;
        }

        if (empty($primaryKey)) {
            LogSysteme::prefixErrorLog('Warning trying to use "'.$entity.'" with incompatible zoom');
        }

        $primaryKeyParam = [];
        if ($primaryKey !== '') {
            $primaryKeyParam = ['filter_egal_' . $primaryKey => $value];
        }

        $contents = $entityQb->findAll(
            null,
            $selectTable,
            $primaryKeyParam + $post,
            $entityQb,
            true
        );

        if ($contents) {
            $this->listeValueEntite[$test][] = $value;
        }

        if (! empty($contents)) {
            return true;
        }

        $this->validate += 1;

        if ($messageSpecifique != '') {
            $this->error .= '<br />' . Trad::strBuild($this->getTrad()->t('Le champ @1@ @2@.'), $nomChamp, $messageSpecifique);
        } else {
            if (strlen($value) > 100) {
                $value = substr($value, 0, 100) . '...';
                $this->error .= '<br />' . Trad::strBuild($this->getTrad()->t('Le code saisi @1@ n\'est pas présent dans la liste des @2@.'), $value, $nomChamp);
            } else {
                //si le client met un code avec un @, cela part en time out.
                $this->error .= '<br />' . Trad::strBuild($this->getTrad()->t('Le code saisi @1@ n\'est pas présent dans la liste des @2@.'), $value, $nomChamp);
            }
        }

        return false;
    }


    /**
     * @param mixed $value
     * @param \PDO $pdo
     * @param array<mixed> $filter
     * @return bool
     */
    public function zoomListe(
        string $path,
        &$value,
        string $nomChamp,
        \PDO $pdo,
        bool $isBlankAllowed = false,
        array $filter = []
    ): bool {

        if (empty($value)) {
            if ($isBlankAllowed) {
                $value = '';
                return true;
            } else {
                $this->validate += 1;
                $this->error .= '<br />' . Trad::strBuild($this->getTrad()->t('Le champ @1@ ne peut pas être vide.'), $nomChamp);
                return false;
            }
        }

        $value = mb_strtoupper(trim($value));

        $zoom = ZoomHelper::getListeCallback($path, $this->getContainer());
        $clauseKey = $zoom->mainId ?? null;
        if ($clauseKey == null) {
            // @phpstan-ignore-next-line
            $entityClass = ZoomHelper::getEntityFromPath($path);

            if (empty($entityClass)) {
                throw new \Exception('Invalid zoom config for "' . $path . '"');
            }

            /** @var \Helpers\QueryBuilder\QueryBuilder */
            $qb = new $entityClass($pdo);
            $primaryKey = $qb->getPrimaryKey();
            if (empty($primaryKey)) {
                throw new \Exception('Incompatible entity "' . $entityClass . '"');
            }

            $clauseKey = 'filter_egal_' . $qb->getTable() . '.' . $primaryKey;
        }
        /** @var callable */
        $callable = $zoom->callable;
        $list = $callable([$clauseKey => $value] + $filter);

        if (!empty($list)) {
            return true;
        }

        $this->validate += 1;

        $trad = $this->getTrad();
        $this->error .= '<br />' . Trad::strBuild(
            $nomChamp
                . $trad->colon()
                . $trad->t('Le code saisi @1@ n\'est pas présent dans la liste.'),
            $value,
        );

        return false;
    }

    public function zoomCentreLivraisonPanier(string $value, string $nomChamp, ?string $codeSte = null): void
    {
        $centreFound = (new Listes($this->pdo))->centreByType('LIVRAISON', [
            'filter_egal_CODE_CTR'  => $value,
            'code_ste'              => $codeSte,
            'fromPanier'            => true,
        ]);

        $this->isFalse($centreFound, Trad::strBuild(
            $this->getTrad()->t('Le code saisi @1@ n\'est pas présent dans la liste des @2@.'),
            $value,
            $nomChamp
        ));
    }

    /**
     * @param mixed $value              : valeur à vérifier
     * @param string $nomChamp          : titre du champs  vérifier
     * @param \PDO $pdo
     * @param boolean $null             : null autorisé ou non ? pas autorisé par defaut
     * @param string $messageSpecifique : message spéficique
     * @return bool
     */
    public function tauxTVA($value, string $nomChamp, $pdo, $null = false, $messageSpecifique = ''): bool
    {
        if (($value === '' || $value === null) && $null) {
            return true;
        }

        if ((!$value) && !$null) {
            $this->validate += 1;
            $this->error .= '<br />' . Trad::strBuild($this->getTrad()->t('Le champ @1@ ne peut pas être vide.'), $nomChamp);
            return false;
        }

        $query = "SELECT CODE_TVA, LIBELLE FROM TVA with (nolock) where CODE_TVA = :codeTaux";

        $data = $pdo->prepare($query);

        $data->bindParam(':codeTaux', $value, PDO::PARAM_INT);

        $data->execute();

        $contents = $data->fetch(PDO::FETCH_ASSOC);

        if ($contents) {
            return true;
        }

        $this->validate += 1;

        if ($messageSpecifique != '') {
            $this->error .= '<br />' . Trad::strBuild($this->getTrad()->t('Le champ @1@ @2@.'), $nomChamp, $messageSpecifique);
        } else {
            $this->error .= '<br />' . Trad::strBuild($this->getTrad()->t('Le code saisi @1@ n\'est pas présent dans la liste des @2@.'), $value, $nomChamp);
        }

        return false;
    }



    /**
     * POUR TOUT LES VALIDATOR SUIVANT
     *
     * @param boolean $null             : null autorisé ou non ? pas autorisé par defaut
     * @param array<mixed> $post               : filtre eventuelle sur l'entity
     */
    public function societeZoom(string $value, string $nomChamp, \PDO $pdo, $null = false, $post = [], string $messageSpecifique = '') : bool
    {
        if (trim($value) == '' && $null) {
            return true;
        }

        if (trim($value) == '' && !$null) {
            $this->validate += 1;
            $this->error .= '<br />' . Trad::strBuild($this->getTrad()->t('Le champ @1@ ne peut pas être vide.'), $nomChamp);
            return false;
        }
        $value = trim($value);
        
        if (!$_SESSION['Session_UsrMultiSoc'] && !empty($_SESSION['Session_Login'])) {
            $societe = new \Modules\Ajax\Repository\Validator($pdo);
            $societe = $societe->societe(strtoupper($value), $post);
            if (empty($societe)) {
                $this->validate += 1;
                if ($messageSpecifique != '') {
                    $this->error .= '<br />' . Trad::strBuild($this->getTrad()->t('Le champ @1@ @2@.'), $nomChamp, $messageSpecifique);
                } else {
                    $this->error .= '<br />' . Trad::strBuild($this->getTrad()->t('Le code saisi @1@ n\'est pas présent dans la liste des @2@.'), $value, $nomChamp);
                }
                return false;
            } else {
                return true;
            }
        } else {
            $societe = new \Modules\Ajax\Repository\Validator($pdo);
            $contents = $societe->allSociete(strtoupper($value), $post);

            if (!empty($contents)) {
                return true;
            }

            $this->validate += 1;
            if ($messageSpecifique != '') {
                $this->error .= '<br />' . Trad::strBuild($this->getTrad()->t('Le champ @1@ @2@.'), $nomChamp, $messageSpecifique);
            } else {
                $this->error .= '<br />' . Trad::strBuild($this->getTrad()->t('Le code saisi @1@ n\'est pas présent dans la liste des @2@.'), $value, $nomChamp);
            }

            return false;
        }
    }

    /**
     * @param mixed $null
     * @param mixed $post
     */
    public function numeroCommandeZoom(string $value, string $nomChamp, \PDO $pdo, $null = false, $post = []) : bool
    {

        if (trim($value) == '' && $null) {
            return true;
        }

        if (trim($value) == '' && !$null) {
            $this->validate += 1;
            $this->error .= '<br />' . Trad::strBuild($this->getTrad()->t('Le champ @1@ ne peut pas être vide.'), $nomChamp);
            return false;
        }

        $value = trim($value);

        $cde = new \Modules\Ajax\Repository\Validator($pdo);
        $cde = $cde->numeroDeCommande($value, $post);
        if (!isset($cde['NO_CDE'])) {
            $this->validate += 1;
            $this->error .= '<br />' . Trad::strBuild($this->getTrad()->t('Le code saisi @1@ n\'est pas présent dans la liste des @2@.'), $value, $nomChamp);
            return false;
        } else {
            return true;
        }
    }

    /**
     * @deprecated use Listes::Devise with 'for_facture'
     * @param mixed $null
     * @param mixed $post
     */
    public function deviseZoom(string $value, string $nomChamp, \PDO $pdo, $null = false, $post = []) : bool
    {

        if (trim($value) == '' && $null) {
            return true;
        }

        if (trim($value) == '' && !$null) {
            $this->validate += 1;
            $this->error .= '<br />' . Trad::strBuild($this->getTrad()->t('Le champ @1@ ne peut pas être vide.'), $nomChamp);
            return false;
        }

        $value = trim($value);

        $devise = new \Modules\Ajax\Repository\Validator($pdo);
        if ($devise->devise($value)) {
            return true;
        } else {
            $this->validate += 1;
            $this->error .= '<br />' . Trad::strBuild($this->getTrad()->t('Le code saisi @1@ n\'est pas présent dans la liste des @2@.'), $value, $nomChamp);
            return false;
        }
    }

    /**
     * @param mixed $null
     * @param mixed $post
     */
    public function sectionImputationZoom(string $value, string $nomChamp, \PDO $pdo, $null = false, $post = []) : bool
    {
        $today = Date('Ymd');

        if (trim($value) == '' && $null) {
            return true;
        }

        if (trim($value) == '' && !$null) {
            $this->validate += 1;
            if (!isset($this->listeValue['sectionImputationZoom'][$value]['error'])) {
                $this->listeValue['sectionImputationZoom'][$value]['error'] = $this->getTrad()->t('Le champ @1@ ne peut pas être vide.');
            }
            $this->error .= '<br />' . Trad::strBuild($this->listeValue['sectionImputationZoom'][$value]['error'], $nomChamp);
            return false;
        }

        $value = trim($value);

        if (!isset($this->listeValue['sectionImputationZoom'][$value])) {
            $sectionImputation = new \Modules\Ajax\Repository\Validator($pdo);
            $sectionImputation = $this->listeValue['sectionImputationZoom'][$value] = $sectionImputation->sectionImputation($value, $post);
        } else {
            $sectionImputation = $this->listeValue['sectionImputationZoom'][$value];
        }

        if (is_array($sectionImputation) && count($sectionImputation) > 0) {
            // date de validité min bloquante
            if (isset($post['min_bloquant']) && $post['min_bloquant'] == 1 && $sectionImputation['DATE_DEB'] > $today) {
                $this->validate += 1;
                $this->error .= '<br />' . $this->getTrad()->t('Cette section d\'imputation n\'est pas encore valide pour cette période.');
                return false;
            }
            // date de validité max bloquante
            if (isset($post['max_bloquant']) && $post['max_bloquant'] == 1 && $sectionImputation['DATE_FIN'] < $today && $sectionImputation['DATE_FIN'] != '00000000') {
                $this->validate += 1;
                $this->error .= '<br />' . $this->getTrad()->t('Cette section d\'imputation n\'est plus valide pour cette période.');
                return false;
            }

            return true;
        } else {
            $this->validate += 1;
            $this->error .= '<br />' . Trad::strBuild($this->getTrad()->t('Le code saisi @1@ n\'est pas présent dans la liste des @2@.'), $value, $nomChamp);
            return false;
        }
    }

    /**
     * Summary of codeGestionZoom
     * @param string $value
     * @param string $nomChamp
     * @param PDO $pdo
     * @param bool $canBeNull
     * @param mixed $post
     * @return bool
     */
    public function codeGestionZoom(
        $value,
        string $nomChamp,
        PDO $pdo,
        bool $canBeNull = false,
        $post = []
    ): bool {

        if (!$_SESSION['IS_CG_ACTIVE']) {
            return true;
        }

        $value = trim($value);
        if (empty($value)) {
            if ($canBeNull) {
                return true;
            }
            $this->validate += 1;
            $this->error .= '<br />' . Trad::strBuild($this->getTrad()->t('Le champ @1@ ne peut pas être vide.'), $nomChamp);
            return false;
        }

        $validator = new \Modules\Ajax\Repository\Validator($pdo);
        if (! $validator->cg(
            strtoupper($value),
            $post['CODE_SI'],
            $post['NUM_LOT'] ?? '',
            $post['AUTHACHAT'] ?? 0,
            $post['CODE_STE'] ?? '',
            $post['valide_obligatoire'] ?? 0,
            $post['cgParId'] ?? 0
        )) {
            $this->validate += 1;
            $this->error .= '<br />' . Trad::strBuild(
                $this->getTrad()->t('Le code saisi @1@ n\'est pas présent dans la liste des @2@.'),
                $value,
                $nomChamp
            );
            return false;
        }

        return true;
    }

    /**
     * @param array<string> $codeGest entity Codegest
     * @param array<string> $commande entity CaEntet
     */
    public function cgValidForCommande(
        array $codeGest,
        array $commande,
        ITrad $trad
    ): bool {
        if ($this->isDateBetween(
            $commande['DTE_PERIO'],
            $codeGest['DTEVALMIN'],
            $codeGest['DTEVALMAX'],
        )) {
            $this->validate += 1;
            $this->error .= '<br />' . Trad::strBuild(
                $trad->t('@1@ n’est plus valide pour cette période.'),
                $trad->t('Ce code gestion')
            );
            return false;
        }
        return true;
    }

    /**
     * @param array<string> $codeComp entity CodeComp
     * @param array<string> $commande entity CaEntet
     */
    public function codeCompValidForCommande(
        array $codeComp,
        array $commande,
        ITrad $trad
    ): bool {
        if ($this->isDateBetween(
            $commande['DTE_PERIO'],
            $codeComp['DATE_DEB'],
            $codeComp['DATE_FIN'],
        )) {
            $this->validate += 1;
            $this->error .= '<br />' . Trad::strBuild(
                $trad->t('@1@ n’est plus valide pour cette période.'),
                $trad->t('Ce code complémentaire')
            );
            return false;
        }
        return true;
    }

    /**
     * @param array<string> $sousComptAna entity CodeComp
     * @param array<string> $commande entity CaEntet
     */
    public function sousComptAnaValidForCommande(
        array $sousComptAna,
        array $commande,
        ITrad $trad
    ): bool {
        if ($this->isDateBetween(
            $commande['DTE_PERIO'],
            $sousComptAna['DATE_MINI'],
            $sousComptAna['DATE_MAXI'],
        )) {
            $this->validate += 1;
            $this->error .= '<br />' . Trad::strBuild(
                $trad->t('@1@ n’est plus valide pour cette période.'),
                $trad->t('Ce sous compte d’analyse')
            );
            return false;
        }
        return true;
    }

    // TODO : move somewhere else
    private function isDateBetween(
        string $date,
        string $min,
        string $max
    ): bool {
        return (
            $max == '00000000' || $max >= $date
        ) && (
            $min == '00000000' || $min <= $date
        );
    }

    /**
     * TODO : move somewhere else
     */
    /**
     * isDateMin
     *
     *
     * @param ITrad $trad
     * @param string $subject
     * @param string $date
     * @param string $min
     * @return bool
     */
    public function isDateMin(
        ITrad $trad,
        string $subject,
        string $date,
        string $min,
        bool $bloquant = true
    ) {
        if ($min != '00000000' && $min > $date) {
            if ($bloquant) {
                $this->setError(Trad::strBuild(
                    $trad->t('@1@ n’est pas encore valide pour cette période.'),
                    $subject
                ));
            } else {
                $this->setErrorNonBloquant(Trad::strBuild(
                    $trad->t('@1@ n’est pas encore valide pour cette période.'),
                    $subject
                ));
            }
            return false;
        }
        return true;
    }
    /**
     * TODO : move somewhere else
     */
    /**
     * isDateMax
     *
     *
     * @param ITrad $trad
     * @param string $subject
     * @param string $date
     * @param string $max
     * @return bool true if subject is valid, false otherwise
     */
    public function isDateMax(
        ITrad $trad,
        string $subject,
        string $date,
        string $max,
        bool $bloquant = true
    ) {
        if ($max != '00000000' && $max < $date) {
            if ($bloquant) {
                $this->setError(Trad::strBuild(
                    $trad->t('@1@ n’est plus valide pour cette période.'),
                    $subject
                ));
            } else {
                $this->setErrorNonBloquant(Trad::strBuild(
                    $trad->t('@1@ n’est plus valide pour cette période.'),
                    $subject
                ));
            }
            return false;
        }
        return true;
    }

    public static function getImpSubject(ITrad $trad, string $classImp): string
    {
        switch ($classImp) {
            case Codgest::class:
                return $trad->t('Ce code gestion');
            case Sectimpu::class:
                return $trad->t('Cette section d’imputation');
            case Codecomp::class:
                return $trad->t('Ce code complémentaire');
            case Sscptana::class:
                return $trad->t('Ce sous compte d’analyse');
        }
        throw new \Exception('Invalid imputation class "' . $classImp . '"');
    }

    /**
     * entityDateValidation
     *
     * @param string $classParent
     * @param string $classChild
     * @param ITrad $trad,
     * @param string $impDateMin
     * @param string $impDateMax
     * @param string $dateRef
     *
     */
    public function entityDateValidation(
        string $classParent,
        string $classChild,
        ITrad $trad,
        string $impDateMin,
        string $impDateMax,
        string $dateRef
    ) :void {
        $paramtr = new Parametr($this->pdo);
        $subject = self::getImpSubject($trad, $classChild);

        switch ($paramtr->getDateMinValiType($classParent, $classChild)) {
            case 'B':
                $this->isDateMin($trad, $subject, $dateRef, $impDateMin, true);
                break;
            case 'N':
                $this->isDateMin($trad, $subject, $dateRef, $impDateMin, false);
                break;
            default:
                // No validation required
        }

        switch ($paramtr->getDateMaxValiType($classParent, $classChild)) {
            case 'B':
                $this->isDateMax($trad, $subject, $dateRef, $impDateMax, true);
                break;
            case 'N':
                $this->isDateMax($trad, $subject, $dateRef, $impDateMax, false);
                break;
            default:
                // No validation required
        }
    }

    /**
     * @param mixed $null
     * @param mixed $post
     */
    public function codeComplementaireZoom(string $value, string $nomChamp, \PDO $pdo, $null = false, $post = []) : bool
    {
        $today = Date('Ymd');

        if (trim($value) == '' && $null) {
            return true;
        }

        if (trim($value) == '' && !$null) {
            $this->validate += 1;
            if (!isset($this->listeValue['codeComplementaireZoom'][$value]['error'])) {
                $this->listeValue['codeComplementaireZoom'][$value]['error'] = $this->getTrad()->t('Le champ @1@ ne peut pas être vide.');
            }

            $this->error .= '<br />' . Trad::strBuild($this->listeValue['codeComplementaireZoom'][$value]['error'], $nomChamp);
            return false;
        }

        $value = trim($value);

        if (!isset($this->listeValue['codeComplementaireZoom'][$value])) {
            $codeComplementaire = new \Modules\Ajax\Repository\Validator($pdo);
            $codeComplementaire = $this->listeValue['codeComplementaireZoom'][$value] = $codeComplementaire->codeComplementaire($value, $post);
        } else {
            $codeComplementaire = $this->listeValue['codeComplementaireZoom'][$value];
        }

        if (is_array($codeComplementaire) && count($codeComplementaire) > 0) {
            // date de validité min bloquante
            if (isset($post['min_bloquant']) && $post['min_bloquant'] == 1 && $codeComplementaire['DATE_DEB'] > $today) {
                $this->validate += 1;
                $this->error .= '<br />' . $this->getTrad()->t('Ce code complémentaire n\'est pas encore valide pour cette période.');
                return false;
            }
            // date de validité max bloquante
            if (isset($post['max_bloquant']) && $post['max_bloquant'] == 1 && $codeComplementaire['DATE_FIN'] < $today && $codeComplementaire['DATE_FIN'] != '00000000') {
                $this->validate += 1;
                $this->error .= '<br />' . $this->getTrad()->t('Ce code complémentaire n\'est plus valide pour cette période.');
                return false;
            }

            return true;
        } else {
            $this->validate += 1;
            $this->error .= '<br />' . Trad::strBuild($this->getTrad()->t('Le code saisi @1@ n\'est pas présent dans la liste des @2@.'), $value, $nomChamp);
            return false;
        }
    }

    /**
     * @param mixed $null
     * @param mixed $post
     */
    public function sousCompteAnalyseZoom(string $value, string $nomChamp, \PDO $pdo, $null = false, $post = []) : bool
    {
        $today = Date('Ymd');

        if (trim($value) == '' && $null) {
            return true;
        }

        if (trim($value) == '' && !$null) {
            $this->validate += 1;
            if (!isset($this->listeValue['sousCompteAnalyseZoom'][$value]['error'])) {
                $this->listeValue['sousCompteAnalyseZoom'][$value]['error'] = $this->getTrad()->t('Le champ @1@ ne peut pas être vide.');
            }
            $this->error .= '<br />' . Trad::strBuild($this->listeValue['sousCompteAnalyseZoom'][$value]['error'], $nomChamp);
            return false;
        }

        $value = trim($value);

        if (!isset($this->listeValue['sousCompteAnalyseZoom'][$value])) {
            $sousCompteAnalyse = new \Modules\Ajax\Repository\Validator($pdo);
            $this->listeValue['sousCompteAnalyseZoom'][$value] = $sousCompteAnalyse = $sousCompteAnalyse->sousCompteAnalyse($value, $post);
        } else {
            $sousCompteAnalyse = $this->listeValue['sousCompteAnalyseZoom'][$value];
        }

        if (is_array($sousCompteAnalyse) && count($sousCompteAnalyse) > 0) {
            // date de validité min bloquante
            if (isset($post['min_bloquant']) && $post['min_bloquant'] == 1 && $sousCompteAnalyse['DATE_MINI'] > $today) {
                $this->validate += 1;
                if (!isset($this->listeValue['sousCompteAnalyseZoom'][$value]['error']['periode'])) {
                    $this->listeValue['sousCompteAnalyseZoom'][$value]['error']['periode'] = $this->getTrad()->t('Ce sous compte d\'analyse n\'est pas encore valide pour cette période.');
                }

                $this->error .= '<br />' . $this->listeValue['sousCompteAnalyseZoom'][$value]['error']['periode'];
                return false;
            }
            // date de validité max bloquante
            if (isset($post['max_bloquant']) && $post['max_bloquant'] == 1 && $sousCompteAnalyse['DATE_MAXI'] < $today && $sousCompteAnalyse['DATE_MAXI'] != '00000000') {
                $this->validate += 1;
                if (!isset($this->listeValue['sousCompteAnalyseZoom'][$value]['error']['periode'])) {
                    $this->listeValue['sousCompteAnalyseZoom'][$value]['error']['sousCompte'] = $this->getTrad()->t('Ce sous compte d\'analyse n\'est plus valide pour cette période.');
                }
                $this->error .= '<br />' . $this->listeValue['sousCompteAnalyseZoom'][$value]['error']['sousCompte'];
                return false;
            }

            return true;
        } else {
            $this->validate += 1;
            if (!isset($this->listeValue['sousCompteAnalyseZoom'][$value]['error']['code'])) {
                $this->listeValue['sousCompteAnalyseZoom'][$value]['error']['code'] = $this->getTrad()->t('Le code saisi @1@ n\'est pas présent dans la liste des @2@.');
            }
            $this->error .= '<br />' . Trad::strBuild($this->listeValue['sousCompteAnalyseZoom'][$value]['error']['code'], $value, $nomChamp);
            return false;
        }
    }

    /**
     * @param mixed $requete
     * @param mixed $null
     * @param mixed $post
     */
    public function zoomRequete(string $value, string $nomChamp, $requete, \PDO $pdo, $null = false, $post = []) : bool
    {

        if (trim($value) == '' && $null) {
            return true;
        }

        if (trim($value) == '' && !$null) {
            $this->validate += 1;
            $this->error .= '<br />' . Trad::strBuild($this->getTrad()->t('Le champ @1@ ne peut pas être vide.'), $nomChamp);
            return false;
        }

        $value = trim($value);

        $validator = new \Modules\Ajax\Repository\Validator($pdo);
        if ($validator->$requete(strtoupper($value), $post)) {
            return true;
        } else {
            $this->validate += 1;
            $this->error .= '<br />' . Trad::strBuild($this->getTrad()->t('Le code saisi @1@ n\'est pas présent dans la liste des @2@.'), $value, $nomChamp);
            return false;
        }
    }

    /**
     * @param mixed $null
     * @param array<mixed> $post
     */
    public function utilisateurZoom(string $value, string $nomChamp, \PDO $pdo, $null = false, $post = []) : bool
    {
        if (trim($value) == '' && $null) {
            return true;
        }

        if (trim($value) == '' && !$null) {
            $this->validate += 1;
            $this->error .= '<br />' . Trad::strBuild($this->getTrad()->t('Le champ @1@ ne peut pas être vide.'), $nomChamp);
            return false;
        }

        $value = trim($value);

        $utilisateur = new \Modules\Ajax\Repository\Validator($pdo);
        if ($utilisateur->utilisateur($value, $post)) {
            return true;
        } else {
            $this->validate += 1;
            $this->error .= '<br />' . Trad::strBuild($this->getTrad()->t('Le code saisi @1@ n\'est pas présent dans la liste des @2@.'), $value, $nomChamp);
            return false;
        }
    }

    /**
     * @param mixed $null
     * @param mixed $post
     */
    public function demandeurZoom(string $value, string $nomChamp, \PDO $pdo, $null = false, $post = []) : bool
    {

        if (trim($value) == '' && $null) {
            return true;
        }

        if (trim($value) == '' && !$null) {
            $this->validate += 1;
            $this->error .= '<br />' . Trad::strBuild($this->getTrad()->t('Le champ @1@ ne peut pas être vide.'), $nomChamp);
            return false;
        }

        $value = trim($value);

        $demandeur = new \Modules\Ajax\Repository\Validator($pdo);
        if ($demandeur->demandeur($value, $post)) {
            return true;
        } else {
            $this->validate += 1;
            $this->error .= '<br />' . Trad::strBuild($this->getTrad()->t('Le code saisi @1@ n\'est pas présent dans la liste des @2@.'), $value, $nomChamp);
            return false;
        }
    }

    /**
     * @param  bool $null
     * @param  array<mixed> $post
     */
    public function delegataireZoom(string $value, string $nomChamp, \PDO $pdo, $null = false, $post = []) : bool
    {

        if (trim($value) == '' && $null) {
            return true;
        }

        if (trim($value) == '' && !$null) {
            $this->validate += 1;
            $this->error .= '<br />' . Trad::strBuild($this->getTrad()->t('Le champ @1@ ne peut pas être vide.'), $nomChamp);
            return false;
        }

        $value = trim($value);

        if ((new Listes($this->pdo))->listDeleg(['filter_CODE' => $value])) {
            return true;
        } else {
            $this->validate += 1;
            $this->error .= '<br />' . Trad::strBuild($this->getTrad()->t('Le code saisi @1@ n\'est pas présent dans la liste des @2@.'), $value, $nomChamp);
            return false;
        }
    }

    /**
     * @param  array<mixed> $post
     * @param  bool $null
     */
    public function societeCommuneZoom(array $post, string $nomChamp, \PDO $pdo, $null = false) : bool
    {

        if (trim($post['CODE_STE']) == '' && $null) {
            return true;
        }

        if (trim($post['CODE_STE']) == '' && !$null) {
            $this->validate += 1;
            $this->error .= '<br />' . Trad::strBuild($this->getTrad()->t('Le champ @1@ ne peut pas être vide.'), $nomChamp);
            return false;
        }

        $post['CODE_STE'] = trim($post['CODE_STE']);

        $societe = new \Modules\Ajax\Repository\Validator($pdo);
        if ($societe->societeCommune($post)) {
            return true;
        } else {
            $this->validate += 1;
            $this->error .= '<br />' . Trad::strBuild($this->getTrad()->t('Le code saisi @1@ n\'est pas présent dans la liste des @2@.'), $post['CODE_STE'], $nomChamp);
            return false;
        }
    }

    /**
     * @param mixed $null
     * @param array<mixed> $post
     */
    public function acheteurZoom(string $value, string $nomChamp, \PDO $pdo, $null = false, $post = []) : bool
    {

        if (trim($value) == '' && $null) {
            return true;
        }

        if (trim($value) == '' && !$null) {
            $this->validate += 1;
            $this->error .= '<br />' . Trad::strBuild($this->getTrad()->t('Le champ @1@ ne peut pas être vide.'), $nomChamp);
            return false;
        }

        $value = trim($value);

        $demandeur = new \Modules\Ajax\Repository\Validator($pdo);
        if ($demandeur->acheteur($value, $post)) {
            return true;
        } else {
            $this->validate += 1;
            $this->error .= '<br />' . Trad::strBuild($this->getTrad()->t('Le code saisi @1@ n\'est pas présent dans la liste des @2@.'), $value, $nomChamp);
            return false;
        }
    }

    /**
     * @param mixed $null
     * @param array<mixed> $post
     */
    public function accordCadreZoom(string $value, string $nomChamp, \PDO $pdo, $null = false, $post = []) : bool
    {

        if (trim($value) == '' && $null) {
            return true;
        }

        if (trim($value) == '' && !$null) {
            $this->validate += 1;
            $this->error .= '<br />' . Trad::strBuild($this->getTrad()->t('Le champ @1@ ne peut pas être vide.'), $nomChamp);
            return false;
        }

        $value = trim($value);

        $accordCadre = new \Modules\Ajax\Repository\Validator($pdo);
        $accordCadre = $accordCadre->accordCadre($value, $post);

        if (is_array($accordCadre) && count($accordCadre) > 0) {
            if ($accordCadre['TYPE_FG'] == 'G') {
                $FsAcd = new \Entity\Model\FsAcd($this->pdo);
                $FsAcd = $FsAcd->fetchAll([], ['filter_egal_CODE_ACD' => $value]);
                // on vérifie si dans le groupement fournisseur de cet accord-cadre, il existe au moins un fournisseur valide et si la DA est de type Execution qu'il ne soit pas un prospect
                if (count($FsAcd) > 0) {
                    foreach ($FsAcd as $fournisseur) {
                        $fourniss = (new Listes($this->pdo))
                            ->Fournisseur(
                                [
                                    'filter_egal_CODE' => $fournisseur['CODE_FOU'],
                                    'valide' => 1,
                                    'TYPE_FRS' => $post['PROSPECT'] ?? ''
                                ],
                                'CODE, RS, RECEP_AUTO, PER_REC_AUTO, REMISE'
                            );
                        if (count($fourniss) > 0) {
                            return true;
                        }
                    }
                }
                $this->validate += 1;
                $this->error .= '<br />' . Trad::strBuild($this->getTrad()->t('Aucun fournisseur du groupement n’est disponible pour l\'accord-cadre @1@.'), $value);
                return false;
            } else {
                $fourniss = (new Listes($this->pdo))
                    ->Fournisseur([
                        'filter_egal_CODE' => $accordCadre['CODE_FOUR'],
                        'valide' => 1,
                        'TYPE_FRS' => $post['PROSPECT'] ?? ''
                    ], 'CODE, RS, RECEP_AUTO, PER_REC_AUTO, REMISE, PROSPECT');
                if (count($fourniss) == 0) {
                    $this->validate += 1;
                    $this->error .= '<br />' . Trad::strBuild($this->getTrad()->t('L\'accord-cadre @1@ a un fournisseur non valide.'), $value);
                    return false;
                }
            }
            return true;
        } else {
            $this->validate += 1;
            $this->error .= '<br />' . Trad::strBuild($this->getTrad()->t('Le code saisi @1@ n\'est pas présent dans la liste des @2@.'), $value, $nomChamp);
            return false;
        }
    }

    /**
     * @param mixed $null
     * @param mixed $post
     */
    public function fournisseurZoom(string $value, string $nomChamp, \PDO $pdo, $null = false, $post = []) : bool
    {

        if (trim($value) == '' && $null) {
            return true;
        }

        if (trim($value) == '' && !$null) {
            $this->validate += 1;
            $this->error .= '<br />' . Trad::strBuild($this->getTrad()->t('Le champ @1@ ne peut pas être vide.'), $nomChamp);
            return false;
        }
        $value = trim($value);

        $fournisseur = new \Modules\Ajax\Repository\Validator($pdo);
        if ($fournisseur->fournisseur($value, $post)) {
            return true;
        } else {
            $this->validate += 1;
            $this->error .= '<br />' . Trad::strBuild(
                $this->getTrad()->t('Le code saisi @1@ n\'est pas présent '
                    . 'dans la liste des @2@.'), // TODO
                $value,
                $nomChamp
            ) . ($post['messageCompl'] ?? '');
            return false;
        }
    }

    /**
     * @param mixed $null
     * @param mixed $post
     */
    public function siteStockZoom(string $value, string $nomChamp, $null = false, $post = []) : bool
    {

        if (trim($value) == '' && $null) {
            return true;
        }

        if (trim($value) == '' && !$null) {
            $this->validate += 1;
            $this->error .= '<br />' . Trad::strBuild($this->getTrad()->t('Le champ @1@ ne peut pas être vide.'), $nomChamp);
            return false;
        }

        $value = trim($value);

        $SsItesto = new SSiteSto($this->pdo);
        if (is_array($SsItesto->find($value, [], $post))) {
            if ($post['CODE_ART'] ?? '' != '') {
                $Sstocklo = new \Entity\Model\Sstocklo($this->pdo);
                $Sstocklo = $Sstocklo->find(['SITE' => $value, 'CODE_ART' => $post['CODE_ART'], 'CODE_STE' => $post['filter_egal_CODE_STE']]);
                if (is_array($Sstocklo)) {
                    if (isset($post['date_art_ouvert']) && $post['date_art_ouvert'] != '' && $Sstocklo['DTE_FERM'] != '00000000' && $Sstocklo['DTE_FERM'] < $post['date_art_ouvert']) {
                        $this->validate += 1;
                        $this->error .= '<br />' . $this->getTrad()->t('Article fermé sur ce site.');
                        return false;
                    }
                } else {
                    $this->validate += 1;
                    $this->error .= '<br />' . $this->getTrad()->t('Article non stocké sur ce site.');
                    return false;
                }
            }
            return true;
        } else {
            $this->validate += 1;
            $this->error .= '<br />' . Trad::strBuild($this->getTrad()->t("Le code saisi @1@ n'est pas présent dans la liste des @2@"), $value, $nomChamp);
            return false;
        }
    }

    /**
     * @param mixed $null
     * @param mixed $post
     * @return bool
     */
    public function sousFamilleZoom(string $value, string $nomChamp, \PDO $pdo, $null = false, $post = []) : bool
    {

        if (trim($value) == '' && $null) {
            return true;
        }

        if (trim($value) == '' && !$null) {
            $this->validate += 1;
            $this->error .= '<br />' . Trad::strBuild($this->getTrad()->t('Le champ @1@ ne peut pas être vide.'), $nomChamp);
            return false;
        }

        $value = trim($value);

        $fournisseur = new \Modules\Ajax\Repository\Validator($pdo);
        if ($fournisseur->SousFamille($value, $post)) {
            return true;
        } else {
            $this->validate += 1;
            $this->error .= '<br />' . Trad::strBuild($this->getTrad()->t('Le code saisi @1@ n\'est pas présent dans la liste des @2@.'), $value, $nomChamp) . ($post['messageCompl'] ?? '');
            return false;
        }
    }

    /**
     * uniteZoom
     *
     * @param  string $value
     * @param  string $nomChamp
     * @param  \PDO $pdo
     * @param  bool $null
     * @param  array<mixed> $post
     * @return bool
     */
    public function uniteZoom(string $value, string $nomChamp, $pdo, $null = false, $post = []): bool
    {
        if (trim($value) == '' && $null) {
            return true;
        }

        if (trim($value) == '' && !$null) {
            $this->validate += 1;
            $this->error .= '<br />' . Trad::strBuild($this->getTrad()->t('Le champ @1@ ne peut pas être vide.'), $nomChamp);
            return false;
        }

        $value = trim($value);

        $uniteEntity = new Unites($this->pdo);
        $unite = $uniteEntity->find($value);
        if ($unite) {
            if (isset($post['ssFamille']) && $post['ssFamille'] != '') {
                $param = Sql::paravrac($this->pdo, 'PARAMGEN', 'SFAM_CTRL_UNITE');

                if ($param != '') {
                    $sousFamilleEntity = new SousFamille($this->pdo);
                    $sousFamille = $sousFamilleEntity->find($post['ssFamille']);

                    if ($sousFamille['UNITEGEST'] != '') {
                        if (mb_strtoupper($sousFamille['UNITEGEST']) != $value) {
                            if ($param == 'N') {
                                $this->nonBloquant = 1;
                                $this->errorNonBloquant = '<br />' . trad::strBuild($this->getTrad()->t('L\'unité @1@ n\'est pas autorisée pour cette sous-famille. Unité de gestion: @2@.'), $value, $sousFamille['UNITEGEST']);
                            } elseif ($param == 'B') {
                                $this->validate += 1;
                                $this->error = '<br />' . trad::strBuild($this->getTrad()->t('L\'unité @1@ n\'est pas autorisée pour cette sous-famille. Unité de gestion: @2@.'), $value, $sousFamille['UNITEGEST']);
                            }
                        }
                    }
                }
            }

            return true;
        } else {
            $this->validate += 1;
            $this->error .= '<br />' . Trad::strBuild($this->getTrad()->t('Le code saisi @1@ n\'est pas présent dans la liste des @2@.'), $value, $nomChamp) . ($post['messageCompl'] ?? '');
            return false;
        }
    }
}
