<?php

namespace Modules\Stock\Controller;

use Entity\Model\CsDon;
use Entity\Model\Paravrac;
use Entity\Model\Sarticle;
use Entity\Model\SbeLign;
use Entity\Model\Sborlot;
use Entity\Model\SbsEnte;
use Entity\Model\SbsLign;
use Entity\Model\SSiteSto;
use Exception;
use GuzzleHttp\Psr7\Response;
use Helpers\ChampsSupplementaire\ChampSupp;
use Modules\GlobalApplication\Repository\LicenceOxalys;
use Modules\Stock\Enum\CodeParametreVracEnum;
use Modules\Stock\Enum\LigneOperationEnum;
use Modules\Stock\Enum\TypeEnteteEnum;
use Modules\Stock\Helper\NumberHelper;
use Modules\Stock\Repository\LigneBonSortieRepo;
use Modules\Stock\Service\CsInitializerService;
use Modules\Stock\Service\Form\LigneBonSortieFormService;
use Modules\Stock\Trait\Controller\LigneControllerTrait;
use Modules\Stock\Trait\Controller\StockContollerTrait;
use Modules\Stock\Validator\LigneBonSortieValidator;
use Skeleton\Controller\Controller;

class LigneBonSortieController extends Controller
{
    use LigneControllerTrait;
    use StockContollerTrait;

    /**
     * @throws Exception
     */
    public function ajouterFormAction(): string
    {
        $post = $this->request->getParsedBody();
        $noBs = $this->request->getAttribute('noBs');
        $bonSortie = (new SbsEnte($this->pdo))->find($noBs);
        $noLigne = (new LigneBonSortieRepo($this->pdo))->getNouveauNoLigne($noBs, 'NO_LIG', 'SBS_LIGN', 'NO_BS');
        $codeEnr = ChampSupp::autoCompletCodeEnr($noBs, $noLigne, 'SBS_LIGN');

        (new CsInitializerService($this->pdo))->initializeCs($post, 'SBS_LIGN', $codeEnr, [
            ['SBS_ENTE', $noBs],
            ['CODECOMP', $post['SBS_LIGN']['INIT']['CODE_COMP']],
            ['SECTIMPU', $post['SBS_LIGN']['INIT']['SECTIMP']],
            ['SSCPTANA', $post['SBS_LIGN']['INIT']['SSCPTEANA']]
        ]);

        return $this->renderer->render('@Stock/LigneBonSortie/ajouter_form', [
            'noBs'            => $noBs,
            'post'            => $post,
            'noLigne'         => $noLigne,
            'bonSortie'       => $bonSortie,
            'typeEntete'      => TypeEnteteEnum::BS,
            'codgesIsDisable' => !(new LicenceOxalys($this->pdo))->codeGestionActive(),
            'siteStock'       => (new SSiteSto($this->pdo))->find(['SITE' => $bonSortie['SITE']]),
            'configAxeImp'    => (new Paravrac($this->pdo))->getCommandeAxeImpConfig($bonSortie['CODE_STE']),
        ]);
    }

    /**
     * @throws Exception
     */
    public function ajouterAction(): Response
    {
        $trad = $this->getTranslationService();
        $post = $this->request->getParsedBody();
        $noBs = $this->request->getAttribute('noBs');
        $bonSortie = (new SbsEnte($this->pdo))->find($noBs);
        $formService = new LigneBonSortieFormService($this->pdo);
        $validator = new LigneBonSortieValidator($this->pdo, $trad);

        $ligneBonSortie = $formService->initEntity($post['SBS_LIGN'], ['NO_BS' => $noBs]);
        if ((new SbsLign($this->pdo))->find(['NO_BS' => $ligneBonSortie['NO_BS'], 'NO_LIG' => $ligneBonSortie['NO_LIG']])) {
            return $this->createJsonResponse(['statut' => 'OK', 'message' => $trad->t('Ligne existante')]);
        }

        $isValid = $validator
            ->validateCodgest($ligneBonSortie)
            ->validateQteSorti($ligneBonSortie)
            ->validateCodeArt($ligneBonSortie, $bonSortie, 'ART')
            ->validateLots($ligneBonSortie, $post['SBSORLOT'], $bonSortie['SITE'])
            ->validateCs('SBS_LIGN', [$ligneBonSortie['NO_BS'], $ligneBonSortie['NO_LIG']], $post)
            ->validateSectimp($ligneBonSortie, CodeParametreVracEnum::IMP_BO_SI__BS, $bonSortie['CODE_STE'])
            ->validateCodeComp($ligneBonSortie, CodeParametreVracEnum::IMP_BO_CDC_BS, $bonSortie['CODE_STE'])
            ->validateSscpteana($ligneBonSortie, CodeParametreVracEnum::IMP_BO_SCA_BS, $bonSortie['CODE_STE'])
            ->isValid()
        ;

        if (!$isValid) {
            return $this->createBloquantJsonErrorResponse([], $validator->getError());
        }

        $formService->updateTotalEntete($bonSortie, $ligneBonSortie, LigneOperationEnum::ADD);

        $post['BON_SORTIE'] = $bonSortie;
        $post['QTE_SORTI_VAR'] = $formService->getQteVar(0, $ligneBonSortie['QTE_SORTI']);
        $formService->flushData($ligneBonSortie, $post);

        return $this->createJsonResponse(['statut' => 'OK']);
    }

    /**
     * @throws Exception
     */
    public function modifierFormAction(): string
    {
        $noBs = $this->request->getAttribute('noBs');
        $noLigne = $this->request->getAttribute('noLigne');
        $bonSortie = (new SbsEnte($this->pdo))->find($noBs);
        $ligneBonSortie = (new SbsLign($this->pdo))->find(['NO_BS' => $noBs, 'NO_LIG' => $noLigne]);
        $stockArticle = (new Sarticle($this->pdo))->find(['CODE_ART' => $ligneBonSortie['ART']]);
        $maxQteSorti = LigneBonSortieValidator::getMaxQteSortie($this->pdo, $ligneBonSortie, (float) $ligneBonSortie['QTE_SORTI']);
        $ligneBonSortie['SBSORLOTS'] = (new Sborlot($this->pdo))->findAll(['NO_BS' => $ligneBonSortie['NO_BS'], 'NO_LIG' => $ligneBonSortie['NO_LIG']]);

        return $this->renderer->render('@Stock/LigneBonSortie/modifier_form', [
            'noBs' => $noBs,
            'noLigne' => $noLigne,
            'typeEntete' => TypeEnteteEnum::BS,
            'maxQteSorti' => $maxQteSorti,
            'ligneBonSortie' => $ligneBonSortie,
            'stockArticle' => $stockArticle,
            'uniteStockee' => $stockArticle['UNITE_STK'],
            'bonSortie' => (new SbsEnte($this->pdo))->find(['NO_BS' => $noBs]),
            'codgesIsDisable' => !(new LicenceOxalys($this->pdo))->codeGestionActive(),
            'siteStock' => (new SSiteSto($this->pdo))->find(['SITE' => $bonSortie['SITE']]),
            'configAxeImp' => (new Paravrac($this->pdo))->getCommandeAxeImpConfig($bonSortie['CODE_STE']),
        ]);
    }

    /**
     * @throws Exception
     */
    public function modifierAction(): Response
    {
        $post = $this->request->getParsedBody();
        $noBs = $this->request->getAttribute('noBs');
        $noLigne = $this->request->getAttribute('noLigne');
        $formService = new LigneBonSortieFormService($this->pdo);
        $validator = new LigneBonSortieValidator($this->pdo, $this->getTranslationService());

        $bonSortie = (new SbsEnte($this->pdo))->find($noBs);
        $ligneBonSortie = (new SbsLign($this->pdo))->find(['NO_BS' => $noBs, 'NO_LIG' => $noLigne]);

        $previousLigneBonSortieTotal = NumberHelper::toFloat($ligneBonSortie['QTE_SORTI']) * NumberHelper::toFloat($ligneBonSortie['PRIX_SORT']);
        $previousQteSortie = NumberHelper::toFloat($ligneBonSortie['QTE_SORTI']);
        $qteSortieVar = $formService->getQteVar($previousQteSortie, $post['SBS_LIGN']['QTE_SORTI']);

        $ligneBonSortie = array_merge($ligneBonSortie, $post['SBS_LIGN']);
        $formService->gererCodgestPropriete($ligneBonSortie);

        $isValid = $validator
            ->validateCodgest($ligneBonSortie)
            ->validateQteSorti($ligneBonSortie, $previousQteSortie)
            ->validateCodeArt($ligneBonSortie, $bonSortie, 'ART')
            ->validateLots($ligneBonSortie, $post['SBSORLOT'], $bonSortie['SITE'])
            ->validateCs('SBS_LIGN', [$ligneBonSortie['NO_BS'], $ligneBonSortie['NO_LIG']], $post)
            ->validateSectimp($ligneBonSortie, CodeParametreVracEnum::IMP_BO_SI__BS, $bonSortie['CODE_STE'])
            ->validateCodeComp($ligneBonSortie, CodeParametreVracEnum::IMP_BO_CDC_BS, $bonSortie['CODE_STE'])
            ->validateSscpteana($ligneBonSortie, CodeParametreVracEnum::IMP_BO_SCA_BS, $bonSortie['CODE_STE'])
            ->isValid();

        if (!$isValid) {
            return $this->createBloquantJsonErrorResponse([], $validator->getError());
        }

        $formService->updateTotalEntete($bonSortie, $ligneBonSortie, LigneOperationEnum::EDIT, $previousLigneBonSortieTotal);

        $post['BON_SORTIE'] = $bonSortie;
        $post['QTE_SORTI_VAR'] = $qteSortieVar;
        $formService->flushData($ligneBonSortie, $post);

        return $this->createJsonResponse(['statut' => 'OK']);
    }

    /**
     * @throws Exception
     */
    public function ligneAction(): string
    {
        $noBs = (int) $this->request->getAttribute('noBs');
        $noLigne = (int) $this->request->getAttribute('noLigne');
        $ligneBonSortie = (new SbsLign($this->pdo))->find(['NO_BS' => $noBs, 'NO_LIG' => $noLigne]);

        return $this->getLigneResponse($noBs, $noLigne, $ligneBonSortie, 'SBS_LIGN', TypeEnteteEnum::BS);
    }

    /**
     * @throws Exception
     */
    public function supprimerAction(): Response
    {
        $sbsEnte = (new SbsEnte($this->pdo));
        $sbsLign = (new SbsLign($this->pdo));
        $noBs = $this->request->getAttribute('noBs');
        $noLigne = $this->request->getAttribute('noLigne');
        $formService = new LigneBonSortieFormService($this->pdo);

        $bonSortie = $sbsEnte->find($noBs);
        $ligneBonSortie = $sbsLign->find(['NO_BS' => $noBs, 'NO_LIG' => $noLigne]);
        $codeEnr = ChampSupp::autoCompletCodeEnr($noBs, $noLigne, 'SBS_LIGN');
        $qteSortieVar = $formService->getQteVar($ligneBonSortie['QTE_SORTI'], 0);
        $formService->updateTotalEntete($bonSortie, $ligneBonSortie, LigneOperationEnum::DELETE);

        $this->pdo->beginTransaction();

        $sbsEnte->merge($bonSortie);
        $sbsLign->delete(['NO_BS' => $noBs, 'NO_LIG' => $noLigne]);
        $formService->updateResteLigneDemandeService($ligneBonSortie, $ligneBonSortie['QTE_SORTI']);
        (new CsDon($this->pdo))->delete(['COD_TAB' => 'SBS_LIGN', 'COD_ENR' => $codeEnr]);
        $formService->updateQteReserveeStockLocal($ligneBonSortie, $qteSortieVar, $bonSortie['SITE']);
        $formService->updateQteReserveeStockArticle((new Sarticle($this->pdo))->find(['CODE_ART' => $ligneBonSortie['ART']]), $ligneBonSortie, $qteSortieVar);
        (new Sborlot($this->pdo))->delete(['NO_BS' => $noBs, 'NO_LIG' => $noLigne]);

        $this->pdo->commit();

        return $this->createJsonResponse(['statut' => 'OK']);
    }
}
