<?php

namespace Modules\Stock\Controller;

use Entity\Model\Sindispo;
use Entity\Model\Slotindi;
use Exception;
use GuzzleHttp\Psr7\Response;
use Helpers\Ariane\Ariane;
use Helpers\ExportTo\Outils;
use Helpers\Filter\FiltreAvance\GeneratorCs;
use Helpers\Outil\Sql;
use Helpers\Pagination\PaginatorGestion;
use Modules\Stock\Enum\TypeEnteteEnum;
use Modules\Stock\Helper\GestionFiltreHelper;
use Modules\Stock\MenuContextuel\IndisponibiliteContextuel;
use Modules\Stock\Repository\IndisponibiliteRepo;
use Modules\Stock\Repository\StockLocalRepo;
use Modules\Stock\Service\Export\IndisponibiliteExportService;
use Modules\Stock\Service\Form\IndisponibiliteFormService;
use Modules\Stock\Service\ParametrageService;
use Modules\Stock\Trait\Controller\StockContollerTrait;
use Modules\Stock\Validator\IndisponibiliteValidator;
use Skeleton\Controller\Controller;

class IndisponibiliteController extends Controller
{
    use StockContollerTrait;

    /**
     * @throws Exception
     */
    public function gestionAction(): string
    {
        $post = $this->request->getParsedBody();
        $trad = $this->getTranslationService();
        $currentUser = $this->getCurrentUser();

        if (Sql::toBool($currentUser['FILT_SIT'])) {
            GestionFiltreHelper::initialiseSiteStockFiltre($post, 'filter_egal_SI#point#SITE', $currentUser['SIT_STO']);
        }

        Ariane::generate(0, $trad->t('Gestion'), [], null, $this->router->generateUri('Stock.Indisponibilite.gestion'));

        (new PaginatorGestion())->generate(20, 'NO_INDISP');
        $indisponibilites = (new IndisponibiliteRepo($this->pdo))->listIndisponibilites($post);
        $infoPagination = PaginatorGestion::getInfoPagination();

        (new IndisponibiliteContextuel($this->pdo, $this->router, $trad))->addMenuContextuelToEntities($indisponibilites);

        $filtreAvance = new GeneratorCs($post, 'SINDISPO', 'SI.NO_INDISP', $this->pdo, $trad);
        $filtreAvance->setFiltre('SI.DTE_MISE', 'date', $trad->t('Date mise en indispo'));
        $filtreAvance->setFiltre('SI.QTE', 'numeric', $trad->t('Quantité indisponible'));
        $filtreAvance->setFiltre('SI.QTE_REST', 'numeric', $trad->t('Quantité restante'));

        return $this->renderer->render('@Stock/Indisponibilite/gestion', [
            'post'             => $post,
            'menuActive'       => 'Stock',
            'infoPagination'   => $infoPagination,
            'indisponibilites' => $indisponibilites,
            'filtreAvance'     => $filtreAvance->getFiltres(),
            'initFiltreAvance' => $filtreAvance->getInit(),
        ]);
    }

    public function popupExportAction() : string
    {
        $tables = ['Entête' => 'SINDISPO'];
        $tab = (new IndisponibiliteExportService($this->pdo, $this->getTranslationService()))->getTab($tables);
        asort($tab);

        return $this->renderer->render('@GlobalApplication/Popup/popupExport', [
            'pathExport' => $this->router->generateUri('Stock.Indisponibilite.exporter'),
            'formFilter' => 'filtres_indisponibilite',
            'coloneExport' => $tab,
            'tabObli' => ['SI.NO_INDISP'],
            'post' => [
                'multiSelectexportFacOBLI1' => 'SI.NO_INDISP',
            ],
        ]);
    }

    /**
     * @throws Exception
     */
    public function exporterAction(): Response
    {
        $post = $this->request->getParsedBody();
        $postFilters = !empty($this->request->getParsedBody()['okFilter']) ? $post: [];
        $indisponibiliteExportService = new IndisponibiliteExportService($this->pdo, $this->getTranslationService());

        $arrayMultiSelect = $indisponibiliteExportService->getArrayMultiSelect($post);
        $listeCS = $indisponibiliteExportService->getListeCS($arrayMultiSelect);

        $indisponibilites = (new IndisponibiliteRepo($this->pdo))->listIndisponibilitesExport($postFilters, implode(',', $arrayMultiSelect));

        $entete = $indisponibiliteExportService->getTableEntete($arrayMultiSelect, $listeCS, 'SINDISPO');
        $champsDate = $indisponibiliteExportService->getChampsParType('DATE');

        foreach ($indisponibilites as &$indisponibilite) {
            /** @var array<int,array<string,string>> $listeCS */
            $indisponibiliteExportService->addChampsSupplementaireValeur($listeCS, $indisponibilite, 'NO_INDISP');
            $indisponibiliteExportService->convertirDates($champsDate, $indisponibilite);
        }

        Outils::gestionEmailAsync2(
            'export_INDISPO_'.date('Ymd'),
            $indisponibilites,
            $this->JWTKEY,
            $this->router,
            $this->getTranslationService(),
            $entete
        );

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

    /**
     * @throws Exception
     */
    public function miseEnIndisponibiliteFormAction(): string|Response
    {
        $trad = $this->getTranslationService();

        Ariane::generate(
            1,
            $trad->t('Mise en indisponibilité'),
            [],
            null,
            $this->router->generateUri('Stock.Indisponibilite.miseEnIndisponibiliteForm')
        );

        return $this->renderer->render('@Stock/Indisponibilite/mise_en_indisponibilite_form');
    }

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

        $indisponibilite = $post['SINDISPO'];

        $validator
            ->validateSite($indisponibilite)
            ->validateArt($indisponibilite)
            ->validateCodTiers($indisponibilite)
            ->validateMotif($indisponibilite)
            ->validateLieu($indisponibilite)
            ->validateQte($indisponibilite, $post['SSTOCKLO'])
            ->validateLots($indisponibilite, $post['SLOTINDI'] ?? [])
        ;

        if ($validator->isValid()) {
            $indisponibiliteFormService = new IndisponibiliteFormService($this->pdo);
            $indisponibilite = $indisponibiliteFormService->initEntity($indisponibilite, [
                'PARAMETRAGE_NUMEROTATION' => (new ParametrageService($this->pdo))->getParametreNumerotation(TypeEnteteEnum::IN)
            ]);
            $post['STOCK_ARTICLE'] = $indisponibiliteFormService->getStockArticleUpdated($indisponibilite);
            $post['STOCK_LOCAL'] = $indisponibiliteFormService->getStockLocalUpdated($indisponibilite);

            $indisponibiliteFormService->flushData($indisponibilite, $post);

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

    /**
     * @throws Exception
     */
    public function remiseEnDisponibiliteFormAction(): string|Response
    {
        $trad = $this->getTranslationService();
        $noIndisp = $this->request->getAttribute('noIndisp');

        if (!$indisponibilite = (new Sindispo($this->pdo))->find(['NO_INDISP' => $noIndisp])) {
            return $this->create404Response($trad->t('Cette indisponibilité n\'existe pas'));
        }

        Ariane::generate(
            1,
            $trad->t('Remise en disponibilité'),
            [],
            null,
            $this->router->generateUri('Stock.Indisponibilite.remiseEnDisponibiliteForm')
        );

        $stockLocalRepo = new StockLocalRepo($this->pdo);
        $stockLocal = $stockLocalRepo->findFromId($indisponibilite['SITE'], $indisponibilite['ART']);
        $lotsIndisponibilite = (new Slotindi($this->pdo))->findAll(['NO_INDISP' => $indisponibilite['NO_INDISP']]);

        return $this->renderer->render('@Stock/Indisponibilite/remise_en_disponibilite_form', [
            'stockLocal' => $stockLocal,
            'indisponibilite' => $indisponibilite,
            'lotsIndisponibilite' => $lotsIndisponibilite,
            'stockLocalGlobal' => $stockLocalRepo->findGlobal($indisponibilite['ART'])
        ]);
    }

    /**
     * @throws Exception
     */
    public function remiseEnDisponibiliteAction(): Response
    {
        $trad = $this->getTranslationService();
        $post = $this->request->getParsedBody();
        $noIndisp = $this->request->getAttribute('noIndisp');
        $validator = new IndisponibiliteValidator($this->pdo, $trad);

        if (!$indisponibilite = (new Sindispo($this->pdo))->find(['NO_INDISP' => $noIndisp])) {
            return $this->create404Response($trad->t('Cette indisponibilité n\'existe pas'));
        }

        $qteRem = $post['QTE_REM'];
        $validator->validateQteRem($indisponibilite, $qteRem)->validateRemiseLots($post['SLOTINDI'] ?? [], $qteRem);

        if ($validator->isValid()) {
            $indisponibilite['QTE_REST'] -= $qteRem;
            $indisponibiliteFormService = new IndisponibiliteFormService($this->pdo, true);
            $post['STOCK_LOCAL'] = $indisponibiliteFormService->getStockLocalUpdated($indisponibilite, false, $qteRem);
            $post['STOCK_ARTICLE'] = $indisponibiliteFormService->getStockArticleUpdated($indisponibilite, false, $qteRem);

            $indisponibiliteFormService->flushData($indisponibilite, $post);

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