<?php

namespace Modules\Stock\Validator;

use Entity\Model\Paravrac;
use Entity\Model\SSiteSto;
use Entity\Model\Tiers;
use Exception;
use Helpers\Trad\ITrad;
use Helpers\Validator\Validator;
use Modules\Ajax\Repository\Listes;
use Modules\Stock\Enum\DemandeServiceTypeEnum;
use Modules\Stock\Repository\DemandeServiceRepo;
use Modules\Stock\Repository\SiteStockRepo;
use Modules\Stock\Service\ParametrageService;
use Modules\Stock\Trait\Validator\EnteteValidatorTrait;
use Modules\Stock\Trait\Validator\ValidatorTrait;
use PDO;

class DemandeServiceValidator extends Validator
{
    use ValidatorTrait;
    use EnteteValidatorTrait;

    protected readonly DemandeServiceRepo $enteteRepo;
    /** @phpstan-ignore-next-line */
    private readonly Paravrac $paravrac;
    /** @phpstan-ignore-next-line */
    private readonly Listes $listes;

    public function __construct(PDO $pdo, ITrad $trad)
    {
        parent::__construct($pdo, $trad);
        $this->enteteRepo = new DemandeServiceRepo($pdo);
        $this->paravrac = new Paravrac($pdo);
        $this->listes = new Listes($pdo);
    }

    /**
     * @param array<string,mixed> $siteStock
     * @param array<string,mixed> $demandeService
     * @return self
     * @throws Exception
     */
    public function validateSiteOrigine(array $demandeService, ?array $siteStock = null): self
    {
        $this->validateSite($demandeService);
        /** @phpstan-ignore-next-line */
        if ($siteStock['SIST_DTE_FERM'] !== '00000000' && $siteStock['SIST_DTE_FERM'] < date('Ymd')) {
            $this->setErrorNonBloquant($this->trad->t('Site de stockage d\'origine fermé'));
        }

        return $this;
    }

    /**
     * @param array<string,string> $demandeService
     * @param array<string|int,array<string,string>> $sitesStockAccessibles
     * @return $this
     * @throws Exception
     */
    public function validateSiteDestinataire(array $demandeService, array $sitesStockAccessibles, bool $obligatoire = false): self
    {
        if (!$obligatoire && !$demandeService['TIERS']) {
            return $this;
        }

        if ($demandeService['TYPE_DEM'] === DemandeServiceTypeEnum::S->name) {
            $hasTiersBlanc = (new Tiers($this->pdo))->find(['CODE' => ""]) !== null;
            $isBlancInterditTiers = (new ParametrageService($this->pdo))->isBlancInterditTiers();

            /** @phpstan-ignore-next-line */
            if (($obligatoire && $isBlancInterditTiers) || ($obligatoire && !$isBlancInterditTiers && !$hasTiersBlanc)) {
                $this->isObligatoire($demandeService['TIERS'], $this->trad->t('Destinataire'));
            }

            $tiers = (new Listes($this->pdo))->listeTiersDestinataires(['TYPE_DEM' => DemandeServiceTypeEnum::S->name], false);
            $this->contentInArray(
                $this->trad->t('Destinataire'),
                $demandeService['TIERS'],
                array_column($tiers, null, 'CODE')
            );
        }

        if ($demandeService['TYPE_DEM'] === DemandeServiceTypeEnum::T->name) {
            if ($obligatoire) {
                $this->isObligatoire($demandeService['TIERS'], $this->trad->t('Destinataire'));
            }

            $siteStockDestinataire = (new SSiteSto($this->pdo))->find(['SITE' => $demandeService['TIERS']]);

            if ((new ParametrageService($this->pdo))->isBonTransfertMultisociete()) {
                unset($sitesStockAccessibles[$demandeService['SITE']]);
                $this->contentInArray($this->trad->t('Destinataire'), $demandeService['TIERS'], $sitesStockAccessibles);
            } else {
                $sitesStockSocieteOrigineAutorises = (new SiteStockRepo($this->pdo))->findSitesSocieteOrigine($demandeService['SITE']);
                $this->contentInArray($this->trad->t('Destinataire'), $demandeService['TIERS'], array_column($sitesStockSocieteOrigineAutorises, null, 'SITE'));
            }

            if ($siteStockDestinataire['SIST_DTE_FERM'] !== '00000000' && $siteStockDestinataire['SIST_DTE_FERM'] < date('Ymd')) {
                $this->setError($this->trad->t('Site de stockage de destination fermé'));
            }
        }

        return $this;
    }

    /**
     * @param array<string,mixed> $demandeService
     * @return $this
     * @throws Exception
     */
    public function validateCodeSte(array $demandeService): self
    {
        $this->zoom(
            'Societe',
            $demandeService['CODE_STE'],
            $this->trad->t('Code société'),
            $this->pdo,
            false,
            ['filter_CODE_STE' => $demandeService['CODE_STE']]
        );

        if ((new SSiteSto($this->pdo))->find(['SITE' => $demandeService['SITE']], ['CODE_STE'])['CODE_STE'] !== $demandeService['CODE_STE']) {
            $this->setError('La société et celle du site de stockage sont différentes');
        }

        return $this;
    }

    /**
     * @param array<string,mixed> $demandeService
     * @return DemandeServiceValidator
     */
    public function validateTypeDemande(array $demandeService): self
    {
        $this->contentInArray($this->trad->t('Type'), $demandeService['TYPE_DEM'], ['S' => 'Sortie', 'T' => 'Transfert']);

        return $this;
    }

    /**
     * @param array<string,mixed> $demandeService
     * @return $this
     */
    public function validateCommentaire(array $demandeService): self
    {
        $this->isStringAvecEspace($this->trad->t('Commentaire'), $demandeService['COMMENTAIRE'], 0, 3000);

        return $this;
    }


    /**
     * @param array<int,array<string,mixed>> $lignesDemandeService
     * @return $this
     */
    public function validateLignesDemandeService(array $lignesDemandeService): self
    {
        if (count($lignesDemandeService) === 0) {
            $this->setError($this->trad->t('Aucune ligne à valider sur cette demande de service !'));
        }

        return $this;
    }

    /**
     * @param array<int,array<string,mixed>> $lignesDemandeService
     * @return $this
     */
    public function validateNoLigneDuplicates(array $lignesDemandeService): self
    {
        $noLigneValues = array_column($lignesDemandeService, 'NO_LIG_DS');
        if (count($noLigneValues) !== count(array_unique($noLigneValues))) {
            $this->setError($this->trad->t('Il existe des doublons dans les numéros de ligne'));
        }

        return $this;
    }
}
