<?php

namespace Modules\Panier\Validator;

use Entity\Model\OxaUserPanierImputation;
use Entity\Model\Paravrac;
use Entity\Model\TypeAchat;
use Helpers\Outil\Sql;
use Helpers\Trad\ITrad;
use Helpers\Trad\Trad;
use Helpers\Validator\Validator;
use Modules\Panier\Repository\PanierEntete;
use Modules\Panier\Repository\ValidationPanierRepository;
use Modules\Panier\Service\OutilPanierService;
use Modules\Panier\Service\PanierFrsService;
use Modules\RechercheArticles\Service\OutilRechercheService;
use Skeleton\Pdo\DbStatement;

class PanierValidator extends Validator
{

    /**
     * @var array<mixed>
     */
    private array $panierEntete;
    private ValidationPanierRepository $validatorPanierRepo;

    public function __construct(\PDO $pdo, ITrad $trad)
    {
        $this->pdo = $pdo;
        $this->trad = $trad;
        
        $this->panierEntete = (new PanierEntete($this->pdo))->getEntetePanier($_SESSION['id_panier'], $_SESSION['id_user']);
        $this->validatorPanierRepo = new ValidationPanierRepository($this->pdo);
    }

    /**
     * @param boolean $CdeComptoir
     * @return void
     */
    public function validatePanier(bool $CdeComptoir = false) : void
    {
        $this->validateEntete($CdeComptoir);
        $this->validateImputation();
        $this->validateBlocFrs();
        $this->validateLigne();

        //todo MSA SPECIFIQUE VALIDE PANIER
    }

    private function validateEntete(bool $CdeComptoir = false):void
    {
        if ($CdeComptoir == false) {
            $listeCSErreur = $this->validatorPanierRepo->getListeCSErreur();

            foreach ($listeCSErreur as $csErreur) {
                if ($csErreur['ID_LIGNE']) {
                    $message = Trad::strBuild(
                        $this->trad->t('Le champ supplémentaire @1@ de l\'article @2@ est obligatoire.'),
                        $csErreur['NOM'],
                        $csErreur['DES_ART']
                    );
                } else {
                    $message = Trad::strBuild($this->trad->t('Le champ supplémentaire d\'entête @1@ est obligatoire.'), $csErreur['NOM']);
                }
                $this->setError($message);
            }
        }
    }

    private function validateImputation():void
    {
        $imputation = (new OxaUserPanierImputation($this->pdo))->findAll(['id_user' => $_SESSION['id_user'], 'id_panier' => $_SESSION['id_panier']]);

        $totalImputation = 0;
        foreach ($imputation as $imput) {
            if ($imput['REPARTITION']<0) {
                $this->setError($this->trad->t('La répartition par éclatement de lignes ne peut pas être negative.'));
                break;
            }
            
            $totalImputation += (float)$imput['REPARTITION'];
        }

        if (!$totalImputation && $imputation) {
            $this->setError($this->trad->t('La répartition par éclatement de lignes des axes d\'imputation doit ête égale à 100.'));
        }
    }

    private function validateBlocFrs():void
    {
        $paniersFrsService = new PanierFrsService($this->pdo);
        $centreZoneGeo = (new OutilRechercheService($this->pdo))->getCentreRecherche($this->panierEntete);

        $listeBlocFrs = $this->validatorPanierRepo->getListeBlocFrs();

        $typeAchat = (new TypeAchat($this->pdo))->fetchAll();
        
        foreach ($listeBlocFrs as $blocFrs) {
            $libFrs = $blocFrs['RS'].' ('.$blocFrs['COD_FOURN'].')';
            if ($typeAchat && $blocFrs['TYP_ACH'] == '' && $blocFrs['COD_FOURN'] != 'RESERVESTOCK' && $blocFrs['COD_FOURN'] != '') {
                $message = Trad::strBuild(
                    $this->trad->t('Vous devez selectionner ou confirmer le choix du type d\'achat pour le fournisseur @1@'),
                    $libFrs
                );
                $this->setError($message);
            }

            if ($blocFrs['DATEDEBCONT'] > $blocFrs['DATEFINCONT']) {
                $message = trad::strBuild(
                    $this->trad->t('La date de début de contrat doit être inférieure à la date de fin de contrat pour le fournisseur @1@'),
                    $libFrs
                );
                $this->setError($message);
            }

            if ($blocFrs['COD_FOURN']) {
                $adresse = $paniersFrsService->adresseCommande($centreZoneGeo, $blocFrs['COD_FOURN']);

                $adresseFound = false;
                foreach ($adresse as $adr) {
                    /*DbStatement::convertDb($adr['ADRESSE']);
                    DbStatement::convertDb($blocFrs['ADR']);*/

                    if ($adr['ADRESSE'] == $blocFrs['ADR'] &&
                        $adr['VILLE1'] == $blocFrs['VILLE1'] &&
                        $adr['CPOSTAL'] == $blocFrs['CPOSTAL'] &&
                        $adr['CODPAYS'] == $blocFrs['CODE_PAYS']
    
                    ) {
                        $adresseFound = true;
                    }
                }
    
                $message = trad::strBuild($this->trad->t('Vous devez sélectionner une adresse de commande valide pour le fournisseur @1@'), $libFrs);
                $this->isFalse((!$adresse || $adresseFound), $message);
            }
        }
    }

    private function validateLigne():void
    {
        $listeLigne = $this->validatorPanierRepo->getListeLigne();
        $parametr = sql::parametr($this->pdo, 'CTRL_DLDA, BLO_DLDA');


        if (!$listeLigne) {
            $this->setError($this->trad->t('Aucune saisie de quantité dans ce panier.'));
        }
        foreach ($listeLigne as $ligne) {
            if ($ligne['qte'] != 0 && !Sql::boolSql($ligne['flg_ligne_ok'])) {
                $this->setError($this->trad->t('Une ligne est en erreur et empêche de soumettre le panier, veuillez la supprimer'));
            }

            if (Sql::boolSql($ligne['RECEP_AUTO']) == false
                && stripos($this->panierEntete['CHPSPECCLT'], 'REGUL')!== false
                && is_array($parametr)
                && sql::boolSql($parametr['CTRL_DLDA'])
                && sql::boolSql($parametr['BLO_DLDA'])
            ) {
                $traitementDA = (int) (new Paravrac($this->pdo))->getValue('PARAMGEN', 'DUREETTDA');
                $dateMini = OutilPanierService::getDateLivraisonMin($ligne['DELAI'], $traitementDA);

                if ($ligne['DATELIVR']<$dateMini) {
                    $message = trad::strBuild(
                        $this->trad->t('Pour l\'article @1@ la date de livraison doit être supérieure ou égale à @1@'),
                        $ligne['DES_ART'],
                        $dateMini
                    );
                    $this->setError($message);
                }
            } elseif (Sql::boolSql($ligne['RECEP_AUTO'])) {
                $messageDteLivr = [];
                if ($ligne['DATEDEBCONT'] == '00000000' || !$ligne['DATEDEBCONT']) {
                    $messageDteLivr[] = " - ".$this->trad->t("Sous l'onglet 'Livraison', la date de début doit être remplie.");
                }
                if ($ligne['DATEFINCONT'] == '00000000' || !$ligne['DATEFINCONT']) {
                    $messageDteLivr[] = " - ".$this->trad->t("Sous l'onglet 'Livraison', la date de fin doit être remplie.");
                }
                if ($ligne['DATEFINCONT'] < $ligne['DATEDEBCONT']) {
                    $messageDteLivr[] = " - ".$this->trad->t("Sous l'onglet 'Livraison', la date de fin doit être supérieure ou égale à la date de début");
                }
                if ($messageDteLivr) {
                    $message = trad::strBuild($this->trad->t('Pour l\'article : @1@'), $ligne['DES_ART'])
                    ."<br/>"
                    .implode("<br/>", $messageDteLivr);
                    $this->setError($message);
                }
            }

            if ($ligne['type_de_ligne'] == 1 && ($ligne['PROVENANCE'] != 'PO' && $ligne['PROVENANCE'] != 'AO') && sql::boolSql($ligne['NOCCGEN'])) {
                $message = trad::strBuild($this->trad->t('Pour l\'article "@1@", le fournisseur est interdit hors catalogue.'), $ligne['DES_ART']);
                $this->setError($message);
            }
        }
    }
}
