<?php

namespace Modules\Stock\Controller\Parametrage;

use Entity\Model\Paravrac;
use Entity\Model\Snoreser;
use Entity\Model\Societe;
use Entity\Model\Sparnum;
use Entity\Model\SSiteSto;
use Exception;
use GuzzleHttp\Psr7\Response;
use Helpers\Outil\Sql;
use Helpers\Pagination\PaginatorGestion;
use Modules\Stock\Enum\TypeEnteteEnum;
use Modules\Stock\Enum\TypeNumerotationEnum;
use Modules\Stock\Enum\TypeParametreVracEnum;
use Modules\Stock\Repository\NumerotationRepo;
use Modules\Stock\Service\ListManagerService;
use Modules\Stock\Service\ParametrageService;
use Modules\Stock\Trait\Controller\StockContollerTrait;
use Modules\Stock\Validator\NumerotationValidator;
use Skeleton\Controller\Controller;
use Throwable;

class NumerotationController extends Controller
{
    use StockContollerTrait;

    /**
     * @throws Exception
     */
    public function numerotationFormAction(): string
    {
        $sparNum = new Sparnum($this->pdo);
        $trad = $this->getTranslationService();
        $codesParametres = (new ListManagerService($trad))->getSectorisationNumerotationCodeParametreList();

        return  $this->renderer->render('@Stock/Parametrage/Numerotation/numerotation_form', [
            'menuActive' => 'Stock',
            'current_route' => $this->router->getNameRoute(),
            'menuLeft' => 'Stock.Numerotation.numerotationForm',
            'listeTypeNums' => (new ListManagerService($trad))->getNumerotationTypeList(),
            'parametresNumerotation' => array_column($sparNum->findGlobals(), null, 'TYPE_ENT'),
            'parametres' => (new ParametrageService($this->pdo))->getParametres('PARASTOGEN', $codesParametres),
        ]);
    }

    /**
     * @throws Exception
     */
    public function numerotationAction(): Response
    {
        $trad = $this->getTranslationService();
        $post = $this->request->getParsedBody();
        $listManagerService = new ListManagerService($trad);
        $validator = new NumerotationValidator($this->pdo, $trad);
        $codesParametres = (new ListManagerService($trad))->getSectorisationNumerotationCodeParametreList();
        $parametres = (new ParametrageService($this->pdo))->getParametres('PARASTOGEN', $codesParametres);

        $parametresNumerotation = $post['SPARNUM'];
        foreach ($parametresNumerotation as $parametreNumerotation) {
            $suffixe = $listManagerService->getTypeEnteteList()[$parametreNumerotation['TYPE_ENT']];
            $isSectorise = Sql::toBool($parametres['SECTNUM' . $parametreNumerotation['TYPE_ENT']]['LIB01PARV']);
            $validator
                ->validateTypeNum($parametreNumerotation, $isSectorise, $suffixe)
                ->validateProchNo($parametreNumerotation, $isSectorise, $suffixe)
                ->validateNoDep($parametreNumerotation, $isSectorise, $suffixe)
            ;
        }

        if ($validator->isValid()) {
            $sparnum = new Sparnum($this->pdo);

            $this->pdo->beginTransaction();
            foreach ($parametresNumerotation as $parametreNumerotation) {
                $sparnum->processAndUpdate($parametreNumerotation);
            }
            $this->pdo->commit();

            return $this->createJsonResponse([
                'statut' => 'OK',
                'redirectRoute' => $this->router->generateUri('Stock.Numerotation.numerotationForm')
            ]);
        } else {
            return $this->createBloquantJsonErrorResponse([], $validator->getError());
        }
    }

    /**
     * @throws Exception
     */
    public function sectoriserAction(): Response
    {
        $societe = new Societe($this->pdo);
        $sparNum = new Sparnum($this->pdo);
        $paravrac = new Paravrac($this->pdo);
        $typeEntete = $this->request->getAttribute('typeEntete');
        $parametre = $paravrac->find(['TYPEPARV' => TypeParametreVracEnum::PARASTOGEN->name, 'CODEPARV' => 'SECTNUM' . $typeEntete]);

        if (Sql::toBool($parametre['LIB01PARV'])) {
            return $this->createJsonResponse(['message' => 'La numérotation ' . $typeEntete . ' est déjà sectorisée'], 403);
        }

        $parametreNumerotation = $sparNum->find(['TYPE_ENT' => $typeEntete, 'CODE_STE' => '']);
        $societes = $societe->fetchAll(['CODE_STE']);
        $parametreNumerotation['CODE_STE'] = $societes[0]['CODE_STE'];
        $parametreNumerotation['RECH_TROU'] = Sql::toBool($parametreNumerotation['RECH_TROU']);

        try {
            $this->pdo->beginTransaction();
            $sparNum->update($parametreNumerotation, ['TYPE_ENT' => $typeEntete, 'CODE_STE' => '']);
            unset($societes[0]);

            foreach ($societes as $societe) {
                $nouveauParametreNumerotation = [
                    'TYPE_ENT' => $typeEntete,
                    'CODE_STE' => $societe['CODE_STE'],
                    'NO_DEP' => 1,
                    'PROCH_NO' => 1,
                    'TYPE_NUM' => TypeNumerotationEnum::I->name
                ];

                $sparNum->merge($nouveauParametreNumerotation);
            }

            $parametre['LIB01PARV'] = Sql::convertBooleenCheckboxForWsdl('O');
            $paravrac->merge($parametre);
            $this->pdo->commit();

            return $this->createJsonResponse(['statut' => 'OK']);
        } catch (Throwable $t) {
            return $this->logAndCreateErrorJsonResponse($t);
        }
    }

    /**
     * @throws Exception
     */
    public function desectoriserAction(): Response
    {
        $sparNum = new Sparnum($this->pdo);
        $paravrac = new Paravrac($this->pdo);
        $typeEntete = $this->request->getAttribute('typeEntete');
        $intervalle = (new NumerotationRepo($this->pdo))->getTypeEnteteIntervalle($typeEntete);
        $parametre = $paravrac->find(['TYPEPARV' => TypeParametreVracEnum::PARASTOGEN->name, 'CODEPARV' => 'SECTNUM' . $typeEntete]);

        if (!Sql::toBool($parametre['LIB01PARV'])) {
            return $this->createJsonResponse(['message' => 'La numérotation ' . $typeEntete . ' n\'est pas sectorisée'], 403);
        }

        try {
            $this->pdo->beginTransaction();
            $sparNum->delete(['TYPE_ENT' => $typeEntete]);
            $parametreNumerotation = [
                'TYPE_ENT' => $typeEntete,
                'CODE_STE' => '',
                'NO_DEP' => $intervalle[0]['MIN_NO_DEP'],
                'PROCH_NO' => $intervalle[0]['MAX_PROCH_NO'],
                'TYPE_NUM' => TypeNumerotationEnum::I->name,
            ];
            $sparNum->insert($parametreNumerotation);
            $parametre['LIB01PARV'] = Sql::convertBooleenCheckboxForWsdl('N');
            $paravrac->merge($parametre);
            $this->pdo->commit();

            return $this->createJsonResponse(['statut' => 'OK', 'sparnum' => $parametreNumerotation]);
        } catch (Throwable $t) {
            return $this->logAndCreateErrorJsonResponse($t);
        }
    }

    /**
     * @throws Exception
     */
    public function sectorisationFormAction(): string
    {
        $trad = $this->getTranslationService();
        $post = $this->request->getParsedBody();
        $typeEntete = $this->request->getAttribute('typeEntete');
        $listeTypeNums = (new ListManagerService($trad))->getNumerotationTypeList();

        (new PaginatorGestion())->generate(20, 'CODE_STE', 'ASC');
        $parametresNumerotation = (new NumerotationRepo($this->pdo))->findAllByTypeEnteteAndCodeSte($typeEntete, $post);
        $parametresNumerotation = array_column($parametresNumerotation, null, 'CODE_STE');
        $infoPagination = PaginatorGestion::getInfoPagination();

        return  $this->renderer->render('@Stock/Parametrage/Numerotation/sectorisation_form', [
            'post' => $post,
            'hasAriane' => true,
            'typeEntete' => $typeEntete,
            'menuActive' => 'Stock',
            'listeTypeNums' => $listeTypeNums,
            'infoPagination' => $infoPagination,
            'parametresNumerotation' => $parametresNumerotation,
            'current_route' => $this->router->getNameRoute(),

        ]);
    }

    /**
     * @throws Exception
     */
    public function sectorisationAction(): Response
    {
        $trad = $this->getTranslationService();
        $post = $this->request->getParsedBody();
        $validator = new NumerotationValidator($this->pdo, $trad);

        $parametresNumerotation = $post['SPARNUM'];
        foreach ($parametresNumerotation as $parametreNumerotation) {
            $suffixe = 'Société : ' . $parametreNumerotation['CODE_STE'];
            $validator
                ->validateTypeNum($parametreNumerotation, false, $suffixe)
                ->validateProchNo($parametreNumerotation, false, $suffixe)
                ->validateNoDep($parametreNumerotation, false, $suffixe)
            ;
        }

        if ($validator->isValid()) {
            $sparnum = new Sparnum($this->pdo);

            $this->pdo->beginTransaction();
            foreach ($parametresNumerotation as $parametreNumerotation) {
                $sparnum->processAndUpdate($parametreNumerotation);
            }
            $this->pdo->commit();

            return $this->createJsonResponse([
                'statut' => 'OK',
                'redirectRoute' => $this->router->generateUri('Stock.Numerotation.numerotationForm')
            ]);
        } else {
            return $this->createBloquantJsonErrorResponse([], $validator->getError());
        }
    }

    /**
     * @throws Exception
     */
    public function isNoEnteteModifiableAction(): Response
    {
        $post = $this->request->getParsedBody();
        $typeEntete = TypeEnteteEnum::tryFrom($post['typeEntete']);
        $site = $post['site'];

        $siteStock = (new SSiteSto($this->pdo))->find($site);
        $parametreNumerotation = (new ParametrageService($this->pdo))->getParametreNumerotation($typeEntete, $siteStock['CODE_STE']);

        return $this->createJsonResponse(['statut' => 'OK', 'isModifiable' => $parametreNumerotation['TYPE_NUM'] !== TypeNumerotationEnum::A->name]);
    }

    /**
     * @throws Exception
     */
    public function noReservationAction(): Response
    {
        $numSession = Sql::getNumSession();
        $snoreser = new Snoreser($this->pdo);
        $post = $this->request->getParsedBody();
        $typeEntete = TypeEnteteEnum::tryFrom($post['typeEntete']);

        $noReservation = [
            'NO_SESS' => $numSession, 'UTIL' => $_SESSION['Session_Login'], 'NO_BE' => '', 'NO_BS' => '', 'NO_INV' => '',
            'NO_MVT' => '', 'NO_INDIS' => '', 'NO_DISP' => '', 'NO_PR' => '', 'NO_BT' => '', 'NO_DS' => ''
        ];
        $noReservation[$typeEntete->getColName()] = $post['noEnte'];

        $this->pdo->beginTransaction();

        $snoreser->delete(['NO_SESS' => $numSession]);
        $snoreser->insert($noReservation);

        $this->pdo->commit();

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