<?php

namespace Modules\Stock\Service;

use Entity\Model\Sarticle;
use Entity\Model\SdsEnte;
use Entity\Model\SdsLign;
use Entity\Model\Sstocklo;
use Exception;
use Modules\Stock\Enum\DemandeServiceTypeEnum;
use Modules\Stock\Enum\SoldeDemandeServiceEnum;
use Modules\Stock\Repository\LigneDemandeServiceRepo;
use PDO;

readonly class SoldeManuelService
{
    public function __construct(private PDO $pdo)
    {
    }

    /**
     * @throws Exception
     */
    public function process(string|int $noDs, SoldeDemandeServiceEnum $soldeDemandeService): void
    {
        $sdsLign = new SdsLign($this->pdo);
        $sdsEnte = new SdsEnte($this->pdo);
        $sArticle = new Sarticle($this->pdo);
        $sStocklo = new Sstocklo($this->pdo);
        $demandeService = $sdsEnte->find(['NO_DS' => $noDs]);
        $lignesDemandeService = $sdsLign->findAll(['NO_DS' => $demandeService['NO_DS']]);

        $this->pdo->beginTransaction();
        $demandeService['SOLDE_DS'] = $soldeDemandeService->name;
        $sdsEnte->merge($demandeService);
        foreach ($lignesDemandeService as $ligneDemandeService) {
            $ligneDemandeService['ETAT_LIG'] = $soldeDemandeService->name;

            if ($ligneDemandeService['TYPE_DS'] === DemandeServiceTypeEnum::S->name) {
                $stockArticle = $sArticle->find(['CODE_ART' => $ligneDemandeService['ART']]);
                $stockArticle['QTE_RES'] = match ($soldeDemandeService) {
                    SoldeDemandeServiceEnum::S => $stockArticle['QTE_RES'] - $ligneDemandeService['RESTE'],
                    SoldeDemandeServiceEnum::E => $stockArticle['QTE_RES'] + $ligneDemandeService['RESTE'],
                    default => $stockArticle['QTE_RES'],
                };
                $sArticle->processAndMerge($stockArticle);
            }

            $stockLocal = $sStocklo->find(['CODE_ART' => $ligneDemandeService['ART'], 'SITE' => $ligneDemandeService['ORIGINE']]);
            $stockLocal['QTE_RES'] = match ($soldeDemandeService) {
                SoldeDemandeServiceEnum::S => $stockLocal['QTE_RES'] - $ligneDemandeService['RESTE'],
                SoldeDemandeServiceEnum::E => $stockLocal['QTE_RES'] + $ligneDemandeService['RESTE'],
                default => $stockLocal['QTE_RES'],
            };
            $sStocklo->processAndMerge($stockLocal);

            $sdsLign->merge($ligneDemandeService);
        }

        $this->pdo->commit();
    }

    /**
     * @param int $noBon
     * @param string $codeTab
     * @return callable
     */
    public function getSoldeAutoCallback(int $noBon, string $codeTab): callable
    {
        return function () use ($noBon, $codeTab) {
            $ligneDemandeServiceRepo = new LigneDemandeServiceRepo($this->pdo);

            match ($codeTab) {
                'SBS_LIGN' => $ligneDemandeServiceRepo->updateEtatLignesFromNoBs($noBon),
                'SBT_LIGN' => $ligneDemandeServiceRepo->updateEtatLignesFromNoBt($noBon),
                default => null
            };

            $noDs = $ligneDemandeServiceRepo->getNoDsFromNoBon($noBon, $codeTab);
            if ($noDs && $ligneDemandeServiceRepo->isDemandeServiceFullySolded($noDs)) {
                $sdsEnte = new SdsEnte($this->pdo);
                $demandeService = $sdsEnte->find(['NO_DS' => $noDs]);
                $demandeService['SOLDE_DS'] = SoldeDemandeServiceEnum::S->name;
                $sdsEnte->merge($demandeService);
            }
        };
    }
}
