<?php

namespace Modules\Stock\TwigExtension;

use Entity\Model\Tiers;
use Exception;
use Helpers\Outil\Roles;
use Modules\Stock\Enum\CodeParametreVracEnum;
use Modules\Stock\Enum\TypeEnteteEnum;
use Modules\Stock\Enum\TypeNumerotationEnum;
use Modules\Stock\Service\ParametrageService;
use PDO;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\ContainerInterface;
use Psr\Container\NotFoundExceptionInterface;
use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;

class ParametreExtension extends AbstractExtension
{
    private PDO $pdo;
    private ParametrageService $parametrageService;


    /**
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function __construct(ContainerInterface $contenaire)
    {
        $this->pdo = $contenaire->get(PDO::class);
        $this->parametrageService = new ParametrageService($this->pdo);
    }

    public function getFunctions(): array
    {
        return [
            new TwigFunction('is_prix_visible', [$this, 'isPrixVisible']),
            new TwigFunction('is_no_modifiable', [$this, 'isNoModifiable']),
            new TwigFunction('is_cg_active', [$this, 'isCodeGestionActive']),
            new TwigFunction('is_si_obligatoire', [$this, 'isSiObligatoire']),
            new TwigFunction('is_cdc_obligatoire', [$this, 'isCdcObligatoire']),
            new TwigFunction('is_sca_obligatoire', [$this, 'isScaObligatoire']),
            new TwigFunction('is_tiers_nullable', [$this, 'isTiersNullable']),
            new TwigFunction('is_blanc_interdit_tiers', [$this, 'isBlancInterditTiers']),
            new TwigFunction('is_qte_theorique_a_masquer', [$this, 'isQteTheoriqueAMasquer']),
            new TwigFunction('has_droit_modification_prix', [$this, 'hasDroitModificationPrix']),
            new TwigFunction('is_bon_transfert_multisociete', [$this, 'isBonTransfertMultisociete']),
            new TwigFunction('is_qte_dispo_computable_with_qte_reservee', [$this, 'isQteDispoComputableWithQteReservee']),
        ];
    }

    /**
     * @return bool
     */
    public function isPrixVisible(): bool
    {
        return !$this->parametrageService->isVisibilitePrixActif() || Roles::droitsUtilisateur($this->pdo, 'ST_PRX_ACC');
    }

    /**
     * @return bool
     */
    public function hasDroitModificationPrix(): bool
    {
        return $this->parametrageService->hasDroitModificationPrix();
    }

    /**
     * @return bool
     */
    public function isBonTransfertMultisociete(): bool
    {
        return $this->parametrageService->isBonTransfertMultisociete();
    }

    /**
     * @return bool
     */
    public function isBlancInterditTiers(): bool
    {
        return $this->parametrageService->isBlancInterditTiers();
    }


    /**
     * @throws Exception
     */
    public function isTiersNullable(): bool
    {
        $hasTiersBlanc = (new Tiers($this->pdo))->find(['CODE' => ""]) !== null;

        return !$this->parametrageService->isBlancInterditTiers() && $hasTiersBlanc;
    }

    /**
     * @return bool
     * @throws Exception
     */
    public function isQteDispoComputableWithQteReservee(): bool
    {
        return $this->parametrageService->isQteDispoComputableWithQteReservee();
    }

    /**
     * @param TypeEnteteEnum $typeEnt
     * @return bool
     * @throws Exception
     */
    public function isSiObligatoire(TypeEnteteEnum $typeEnt): bool
    {
        $codeParv = match ($typeEnt) {
            TypeEnteteEnum::BS => CodeParametreVracEnum::IMP_BO_SI__BS,
            TypeEnteteEnum::BE => CodeParametreVracEnum::IMP_BO_SI__BE,
            TypeEnteteEnum::DS => CodeParametreVracEnum::IMP_BO_SI__DS,
            default => throw new Exception('Aucun paramétrage de SI n\'existe pour les entêtes de type '. $typeEnt->name)
        };

        return !$this->parametrageService->isImputationFacultative($codeParv);
    }

    /**
     * @param TypeEnteteEnum $typeEnt
     * @return bool
     * @throws Exception
     */
    public function isCdcObligatoire(TypeEnteteEnum $typeEnt): bool
    {
        $codeParv = match ($typeEnt) {
            TypeEnteteEnum::BS => CodeParametreVracEnum::IMP_BO_CDC_BS,
            TypeEnteteEnum::BE => CodeParametreVracEnum::IMP_BO_CDC_BE,
            TypeEnteteEnum::DS => CodeParametreVracEnum::IMP_BO_CDC_DS,
            default => throw new Exception('Aucun paramétrage de CDC n\'existe pour les entêtes de type '. $typeEnt->name)
        };

        return !$this->parametrageService->isImputationFacultative($codeParv);
    }

    /**
     * @param TypeEnteteEnum $typeEnt
     * @return bool
     * @throws Exception
     */
    public function isScaObligatoire(TypeEnteteEnum $typeEnt): bool
    {
        $codeParv = match ($typeEnt) {
            TypeEnteteEnum::BS => CodeParametreVracEnum::IMP_BO_SCA_BS,
            TypeEnteteEnum::BE => CodeParametreVracEnum::IMP_BO_SCA_BE,
            TypeEnteteEnum::DS => CodeParametreVracEnum::IMP_BO_SCA_DS,
            default => throw new Exception('Aucun paramétrage de SCA n\'existe pour les entêtes de type '. $typeEnt->name)
        };

        return !$this->parametrageService->isImputationFacultative($codeParv);
    }

    /**
     * @param array<string,string> $parametreNumerotation
     * @return bool
     */
    public function isNoModifiable(?array $parametreNumerotation): bool
    {
        return !$parametreNumerotation || in_array($parametreNumerotation['TYPE_NUM'], [TypeNumerotationEnum::I->name, TypeNumerotationEnum::M->name], true);
    }

    public function isQteTheoriqueAMasquer(): bool
    {
        return $this->parametrageService->isQteTheoriqueAMasquer();
    }

    public function isCodeGestionActive(): bool
    {
        return $this->parametrageService->isCodeGestionActive();
    }
}
