<?php

namespace Modules\Stock\Validator;

use DateMalformedStringException as DateMalformedStringExceptionAlias;
use DateTime;
use Entity\Model\Paravrac;
use Entity\Model\Sstocklo;
use Exception;
use Helpers\Outil\Sql;
use Helpers\Parametres\Constante;
use Helpers\Trad\ITrad;
use Helpers\Trad\Trad;
use Helpers\Validator\Validator;
use Modules\Ajax\Repository\Listes;
use Modules\Stock\Helper\StringHelper;
use Modules\Stock\Trait\Validator\LigneValidatorTrait;
use Modules\Stock\Trait\Validator\ValidatorTrait;
use PDO;

class LigneBonEntreeValidator extends Validator
{
    use ValidatorTrait;
    use LigneValidatorTrait;

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

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

    /**
     * @param array<string,mixed> $ligneBonEntree
     * @return self
     */
    public function validateQteEnt(array $ligneBonEntree): self
    {
        $this->isFloat($this->trad->t('Quantité'), $ligneBonEntree['QTE_ENT'], Constante::formatQTE, true, null, 0);

        return $this;
    }

    /**
     * @param array<string,mixed> $ligneBonEntree
     * @return self
     */
    public function validatePrixEnt(array $ligneBonEntree): self
    {
        $this->isFloat($this->trad->t('Prix d\'entrée'), $ligneBonEntree['PRIX_ENT'], Constante::formatPU);

        return $this;
    }

    /**
     * @param array<string,mixed> $ligneBonEntree
     * @param array<int,array<string,mixed>> $lotsBonEntree
     * @return $this
     * @throws Exception
     */
    public function validateLots(array $ligneBonEntree, ?array &$lotsBonEntree, bool $convertDate = false): self
    {
        if (empty($lotsBonEntree)) {
            return $this;
        }

        $total = 0;
        $noLots = [];
        foreach ($lotsBonEntree as &$lotBonEntree) {
            if ($convertDate) {
                $lotBonEntree['DTE_PEREM'] = $lotBonEntree['DTE_PEREM'] !== '00000000' ? (new DateTime($lotBonEntree['DTE_PEREM']))->format('d/m/Y'): "";
            }

            $this->isDate($lotBonEntree['DTE_PEREM'], '', '', true, Trad::strBuild($this->trad->t('Date de péremption (lot n°@1@)'), $lotBonEntree['NO_LOT']));
            $this->isObligatoire($lotBonEntree['NO_LOT'], Trad::strBuild($this->trad->t('N° Lot (lot n°@1@)'), $lotBonEntree['NO_LOT']));
            StringHelper::toFloat($lotBonEntree, ['QTE_LOT']);

            $total += $lotBonEntree['QTE_LOT'];
            $noLots[] = $lotBonEntree['NO_LOT'];

            $this->isFloat(Trad::strBuild($this->trad->t('Quantité (lot n°@1@)'), $lotBonEntree['NO_LOT']), $lotBonEntree['QTE_LOT'], Constante::formatQTE, true, null, 0);
        }

        StringHelper::toFloat($ligneBonEntree, ['QTE_ENT']);
        if ($ligneBonEntree['QTE_ENT'] !== $total) {
            $this->setError($this->trad->t('La somme des quantités des lots doit être égale à la quantité de la ligne.'));
        }
        if (count($noLots) !== count(array_unique($noLots))) {
            $this->setError($this->trad->t('Les lots ne peuvent avoir le même numéro.'));
        }

        return $this;
    }

    /**
     * @param array<string,mixed> $ligneBonEntree
     * @return $this
     */
    public function validateStockArticle(array $ligneBonEntree): self
    {
        $this->zoom(
            'Sstocklo',
            $ligneBonEntree['CODE_ART'],
            $this->trad->t('Code article'),
            $this->pdo,
            false,
            ['filter_egal_CODE_ART' => $ligneBonEntree['CODE_ART']]
        );

        return $this;
    }

    /**
     * @param array<string,mixed> $ligneBonEntree
     * @param array<string,mixed> $bonEntree
     * @return LigneBonEntreeValidator
     * @throws Exception
     */
    public function validateMouvementOuvert(array $ligneBonEntree, array $bonEntree): self
    {
        $stockLocal = (new Sstocklo($this->pdo))->find(['SITE' => $bonEntree['SITE'], 'CODE_ART' => $ligneBonEntree['CODE_ART']]);
        if (Sql::toBool($stockLocal['MVT_VERR'])) {
            $this->setError($this->trad->t('Mouvements verrouillés pour l\'Article'));
        }

        return $this;
    }

    /**
     * @param array<string,mixed> $ligneBonEntree
     * @param array<string,mixed> $bonEntree
     * @return LigneBonEntreeValidator
     * @throws DateMalformedStringExceptionAlias
     * @throws Exception
     */
    public function validateArticleOuvert(array $ligneBonEntree, array $bonEntree): self
    {
        $stockLocal = (new Sstocklo($this->pdo))->find(['SITE' => $bonEntree['SITE'], 'CODE_ART' => $ligneBonEntree['CODE_ART']]);
        if ($stockLocal['DTE_FERM'] !== '00000000' && $stockLocal['DTE_FERM'] < $bonEntree['DTE_CREAT']) {
            $this->setError(Trad::strBuild($this->trad->t('Article fermé depuis le @1@'), (new DateTime($stockLocal['DTE_FERME']))->format('d/m/Y')));
        }

        return $this;
    }
}
