<?php

namespace Modules\Reception\Controller;

use Entity\Model\BrLigne;
use Entity\Model\BrRecep;
use Entity\Model\CCLDoc;
use Entity\Model\OxaBrLigne;
use Entity\Model\PJTypes;
use Entity\Model\SbrLots;
use GuzzleHttp\Psr7\Response;
use Helpers\Ariane\Ariane;
use Helpers\Ariane\ArianeSub;
use Helpers\CaracCompl\CaracCompl;
use Helpers\ChampsSupplementaire\ChampSupp;
use Helpers\Fichier\Fichier;
use Helpers\Log\LogSysteme;
use Helpers\Outil\Date;
use Helpers\Outil\Roles;
use Helpers\Outil\Sql;
use Helpers\Pagination\PaginatorGestion;
use Helpers\Parametres\Constante;
use Helpers\Trad\ITrad;
use Helpers\Trad\Trad;
use Helpers\Validator\Validator;
use Modules\Reception\Repository\CreationBR;
use Modules\Reception\Repository\Lot;
use Modules\Reception\Service\CreationBRService;
use Modules\Reception\Service\IncidentService;
use Modules\Reception\Service\LotService;
use Modules\Reception\Service\ModifBRService;
use Modules\Reception\WebService\BR;
use SimpleXMLElement;
use Skeleton\Controller\Controller;
use Helpers\Session\ParseBase1;

class CreationBRController extends Controller
{
    /**
     * @var array<mixed>
     */
    protected array $droits = [];

    /**
     * @var array<mixed>
     */
    protected array $params = [];

    private CreationBRService $service;
    private ModifBRService $serviceModif;
    private LotService $serviceLot;
    private IncidentService $incidentService;
    private CreationBR $repository;
    private Lot $repositoryLot;
    private BR $wsdlManager;
    private Validator $validator;
    private ChampSupp $csManager;
    private PaginatorGestion $paginator;
    private ITrad $trad;



    /**
     * init
     * gestion des droits
     *
     * @return void
     */
    public function init(): void
    {
        $this->service            = new CreationBRService($this->pdo, $this->getTranslationService());
        $this->serviceModif       = new ModifBRService($this->pdo);
        $this->serviceLot         = new LotService($this->pdo, $this->getTranslationService());
        $this->incidentService    = new IncidentService($this->pdo, $this->getTranslationService());
        $this->repository         = new CreationBR($this->pdo);
        $this->repositoryLot      = new Lot($this->pdo);
        $this->wsdlManager        = new BR();
        $this->validator          = $this->createValidator();
        $this->csManager          = new ChampSupp($this->pdo);
        $this->paginator          = new PaginatorGestion();
        $this->trad               = $this->getTranslationService();

        $droits = [
            'HA_BR_PX' => Roles::droitsUtilisateur($this->pdo, 'HA_BR_PX', $_SESSION["Session_Login"]), // Droit de visu des prix des commandes sur BR
            'HA_CA_SPM' => Roles::droitsUtilisateur($this->pdo, 'HA_CA_SPM', $_SESSION["Session_Login"]), // Droit de solder manuellement la commande si réception partielle
            'HA_BR_VAL' => Roles::droitsUtilisateur($this->pdo, 'HA_BR_VAL', $_SESSION["Session_Login"]), // Droit de valider un bon de réception
        ];

        $params = $this->service->getCreationParam();

        $this->droits = $droits;
        $this->params = $params;
    }

    public function creatEditAction(): string
    {
        $post   = $this->request->getParsedBody();
        $id     = $this->request->getAttribute('id');
        $idDoc  = $this->request->getAttribute('idDoc');
        $tab    = $this->request->getAttribute('tab') ?? 'lines';
        $order  = $this->request->getAttribute('order');
        $type   = $this->request->getAttribute('type');
        $mode   = $this->request->getAttribute('mode');
        $init   = $this->request->getAttribute('init');

        // traitement du paramètre order en fonction du contexte : si on est en modification, le numéro de commande devient un numéro de BR mais doit rester le numéro de commande dans les URL
        $initOrder = $order;
        $initBr = '';

        // création de bon de réception si type === 'R'
        if ($type == 'R') {
            // gestion de la numérotation des BR
            // on vérifie si la numérotation est sectorisée ou non
            $typeNumBR = $this->params['MODE_NUM'];

            // on récupère les taux et montant par défaut pour les réceptions excédentaires, liés au type de document de la commande
            $this->params = $this->service->getTauxMargeBrExcedentaire($order, $this->params);

            // init du BR en cas de création
            if ($mode == 'C') {
                // initialisation de la date du bon de livraison à la date du jour si elle n'est pas renseignée
                if (isset($post['DATE_BL']) && $post['DATE_BL'] != '') {
                    $dateBL = Date::dateToSql($post['DATE_BL']);
                } elseif ($dateBLBDD = $this->repository->getDateBL($order)) {
                    $dateBL = $dateBLBDD;
                } else {
                    $dateBL = '00000000';
                }

                // initialisation de la date de période
                if ($this->params['BR_DATE_PERIODE_INIT'] == 'BL' && $dateBL != '00000000') {
                    $datePer = (string)$dateBL;
                } else {
                    $datePer = \date('Ymd');
                }

                // gestion de l'init : si $init est à 1, c'est la première fois qu'on visite cette page et on réinitialise oxa_br_entete ainsi que oxa_br_ligne et les CS
                if ($init || ($post['RECEP_INIT'] ?? false)) {
                    $openHeading = $_SESSION['BR']['entete_crea_br_open'] ?? true;
                    unset($_SESSION['BR']);

                    // on vérifie la valeur d'init si un type de réception a été sélectionné
                    $initRecep = $post['RECEP_INIT'] ?? 'ECHUE';

                    // on initialise les paramètres enregistrés en session
                    $_SESSION['BR']['entete_crea_br_open'] = $openHeading;
                    $_SESSION['BR']['init_recep'] = $initRecep;
                    $_SESSION['BR']['only_ral'] = true;

                    // on n'init que les lignes en changeant RECEP_INIT
                    if ($init == '1') {
                        $_SESSION['BR']['entete_crea_br_open'] = true;
                        $br = $this->service->resetBrEntete($order, $_SESSION['Session_Login']);

                        // init des CS du BR (le numéro de BR est donné à l'enregistrement, donc en attendant on enregistre via le code 'BR_OXAPROC')
                        $this->service->initCsBr();

                        // on supprime les fichiers dans tmp qui pourraient être restés lors d'une précédente création interrompue
                        $this->service->deleteTmpFiles();

                        // on crée ensuite le fichier temporaire de gestion des docs internes
                        $this->service->createDocFileManager();
                    } else {
                        $br = $this->repository->getInfoBrEntete($_SESSION['Session_Login']);
                    }

                    // on initialise les lignes de oxa_br_ligne
                    $lineDetails = $this->service->resetOxaBrLigne($order, $_SESSION['Session_Login'], $datePer, $initRecep, $this->params, $init);

                    // on initialise les lignes de oxa_br_ligne_lots
                    $this->serviceLot->initOxaBrLigneLot($order);

                    // init des caractéristiques complémentaires des lignes du BR
                    $this->service->initCcBr();
                } else {
                    $br = $this->repository->getInfoBrEntete($_SESSION['Session_Login']);
                }

                $ariane = $this->trad->t('Création bon de réception');
                ariane::setFocus($order);
            } else {
                // init du BR en cas de modification
                $initBr = $order;
                $order = $this->service->getOrderFromBr($initBr);

                // gestion de l'init : si $init est à 1, c'est la première fois qu'on visite cette page et on réinitialise oxa_br_entete ainsi que oxa_br_ligne et les CS
                if ($init || ($post['RECEP_INIT'] ?? false)) {
                    unset($_SESSION['BR']);
                    // on vérifie la valeur d'init si un type de réception a été sélectionné
                    $initRecep = $post['RECEP_INIT'] ?? 'NO_INIT';
                    $_SESSION['BR']['init_recep'] = $initRecep;
                    $_SESSION['BR']['only_ral'] = false;

                    // on n'init que les lignes en changeant RECEP_INIT
                    if ($init == '1') {
                        $br = $this->serviceModif->resetOxaBrEnteteModif($initBr);

                        // on initialise les paramètres enregistrés en session
                        $_SESSION['BR']['entete_crea_br_open'] = true;

                        // on supprime les fichiers dans tmp qui pourraient être restés lors d'une précédente création interrompue
                        $this->service->deleteTmpFiles();

                        // on crée les fichiers dans tmp avec les infos du BR en cours de modif (pour les docs att)
                        $this->service->createDocFileManager($br['no_br']??0);
                    } else {
                        $br = $this->repository->getInfoBrEntete($_SESSION['Session_Login']);
                    }

                    // on initialise les lignes de oxa_br_ligne
                    $lineDetails = $this->serviceModif->resetOxaBrLigneModif($initBr, $init);

                    // on initialise les lignes de oxa_br_ligne_lots
                    $this->serviceLot->initOxaBrLigneLotModif($initBr, $br['no_cde']);
                } else {
                    $br = $this->repository->getInfoBrEntete($_SESSION['Session_Login']);
                }

                $ariane = $this->trad->t('Modification bon de réception');
                ariane::setFocus($initBr);
            }

            // on récupère les lignes qui nécessitent une répartition par lots et sont en réception
            $batchLines = $this->serviceLot->getBatchLines();

            // on récupère les lignes qui comptent des caractéristiques complémentaires
            $compLines = $this->service->getLinesWithAdditionalCharacteristics($post);

            Ariane::generate(2, $ariane);
            ArianeSub::init();
            ArianeSub::generate(
                0,
                0,
                $this->trad->t('Lignes'),
                $this->router->generateUri(
                    'Reception.CreationBR.creatEdit',
                    [
                        'order'   => $initOrder,
                        'type'    => $type,
                        'mode'    => $mode,
                        'init'    => 0
                    ]
                ),
                1
            );
            ArianeSub::generate(
                0,
                1,
                $this->trad->t('Incidents'),
                $this->router->generateUri(
                    'Reception.CreationBR.creatEdit',
                    [
                        'order' => $initOrder,
                        'type' => $type,
                        'mode' => $mode,
                        'init' => 0,
                        'tab' => 'incidents'
                    ]
                ),
                0,
                [],
                'sub_incidents'
            );
            ArianeSub::generate(
                0,
                2,
                $this->trad->t('Documents internes'),
                $this->router->generateUri(
                    'Reception.CreationBR.creatEdit',
                    [
                        'order' => $initOrder,
                        'type' => $type,
                        'mode' => $mode,
                        'init' => 0,
                        'tab' => 'documents'
                    ]
                )
            );
            if (!empty($compLines)) {
                ArianeSub::generate(
                    0,
                    3,
                    $this->trad->t('Caractéristiques Complémentaires'),
                    $this->router->generateUri(
                        'Reception.CreationBR.creatEdit',
                        [
                            'order' => $initOrder,
                            'type' => $type,
                            'mode' => $mode,
                            'init' => 0,
                            'tab' => 'caracComp'
                        ]
                    )
                );
            }
            if (!empty($batchLines)) {
                ArianeSub::generate(
                    0,
                    4,
                    $this->trad->t('Répartition par lots'),
                    $this->router->generateUri(
                        'Reception.CreationBR.creatEdit',
                        [
                            'order' => $initOrder,
                            'type' => $type,
                            'mode' => $mode,
                            'init' => 0,
                            'tab' => 'repartition'
                        ]
                    ),
                    0,
                    [],
                    'sub_batch'
                );
            }

            $receptionInit = [
                'NO_INIT'   => $this->trad->t('Pas d\'initialisation'),
                'SOLDE'     => $this->trad->t('Réception du solde'),
                'ECHUE'     => $this->trad->t('Réception échue'),
            ];

            // on prépare un tooltip d'info pour la switch d'init du BR, qui alerte sur le fait que changer l'init efface ce qui a été fait sur le BR
            $tooltipInit = $this->trad->t('Attention : en changeant l\'initialisation, vous remettrez à zéro ce bon de réception');

            $noCcInfo = $this->trad->t('Aucune caractéristique complémentaire attendue pour les lignes sélectionnées.');
            $noBatchInfo = $this->trad->t('Aucune répartition par lots attendue pour les lignes sélectionnées.');

            $selectedLines = $this->service->getSelectedLines();

            $orderDetails = $this->repository->orderDetails($order);

            switch ($tab) {
                case 'lines':
                    $this->paginator->generate(0, 'no_ligne_cde');
                    $lineDetails = $this->repository->getOxaBrLigne($_SESSION['Session_Login']);
                    break;

                case 'documents':
                    ArianeSub::generate(
                        0,
                        2,
                        $this->trad->t('Documents internes'),
                        $this->router->generateUri(
                            'Reception.CreationBR.creatEdit',
                            [
                                'order' => $initOrder,
                                'type' => $type,
                                'mode' => $mode,
                                'init' => 0,
                                'tab' => 'documents'
                            ]
                        ),
                        1
                    );
                    $documentsList = $this->service->getInfoDoc();
                    break;

                case 'newDoc':
                    $pathEnregistrement = $this->router->generateUri(
                        'Reception.Document.saveNewDoc',
                        ['NO_DA' => 'BR_RECEP', 'id' => $initOrder]
                    );

                    if ($idDoc) {
                        $arianeTitle = $this->trad->t('Modification document');
                        $docAtt = $this->service->getInfoDoc($idDoc);
                        $pathEnregistrement = $this->router->generateUri(
                            'Reception.Document.saveEditDoc',
                            ['NO_DA' => 'BR_RECEP', 'id' => $initOrder]
                        );
                    } else {
                        $arianeTitle = $this->trad->t('Nouveau document interne');
                        $docAtt['AUTEUR']   = $_SESSION['Session_Login'];
                        $docAtt['CENTRE']   = $_SESSION["Session_CodeCtrLivraison"];
                        $docAtt['DT_PARUT'] = date('Ymd');
                    }

                    $documentsList = $this->service->getInfoDoc();

                    ArianeSub::generate(
                        0,
                        4,
                        $arianeTitle,
                        $this->router->generateUri(
                            'Reception.CreationBR.creatEdit',
                            [
                                'order' => $initOrder,
                                'type' => $type,
                                'mode' => $mode,
                                'init' => 0,
                                'tab' => 'newDoc'
                            ]
                        ),
                        1
                    );

                    $pathBack = $this->router->generateUri(
                        'Reception.CreationBR.creatEdit',
                        [
                            'order' => $initOrder,
                            'type' => $type,
                            'mode' => $mode,
                            'init' => 0
                        ]
                    );

                    $tmpDocTypes = (new PJTypes($this->pdo))->fetchAll();
                    $docTypes = [];
                    foreach ($tmpDocTypes as $type) {
                        $docTypes[$type["PJ_TYPE"]] = $type["PJLIBELLE"];
                    }
                    break;

                case 'newIncident':
                    $incident = $this->incidentService->getIncident();
                    if (count($incident) > 0) {
                        $arianeTitle = $this->trad->t('Modification incident');
                    } else {
                        $arianeTitle = $this->trad->t('Nouvel incident');
                    }

                    ArianeSub::generate(0, 4, $arianeTitle, $this->router->generateUri('Reception.CreationBR.creatEdit', ['order' => $initOrder, 'type' => $type, 'mode' => $mode, 'init' => 0, 'tab' => 'newIncident']), 1);
                    $pathBack = $this->router->generateUri('Reception.CreationBR.creatEdit', ['order' => $initOrder, 'type' => $type, 'mode' => $mode, 'init' => 0]);
                    $pathEnregistrement = $this->router->generateUri('Reception.Incident.saveIncident', ['id' => $initOrder, 'type' => $type, 'mode' => $mode]);

                    $incidentTypes = [
                        'REFUS'     => $this->trad->t('Quantité refusée'),
                        'LIVINC'    => $this->trad->t('Livraison incomplète'),
                        'RET LIV'   => $this->trad->t('Retard de livraison'),
                        'REPORT'    => $this->trad->t('Report de livraison'),
                        'REL REC'   => $this->trad->t('Relance date livr.'),
                    ];
                    break;

                case 'incidents':
                    ArianeSub::generate(
                        0,
                        1,
                        $this->trad->t('Incidents'),
                        $this->router->generateUri(
                            'Reception.CreationBR.creatEdit',
                            ['order' => $initOrder, 'type' => $type, 'mode' => $mode, 'init' => 0, 'tab' => 'incidents']
                        ),
                        1,
                        [],
                        'sub_incidents'
                    );

                    $incident = $this->incidentService->getIncident();
                    $incidentLines = $this->incidentService->getIncidentLines($order);
                    break;

                case 'caracComp':
                    ArianeSub::generate(
                        0,
                        3,
                        $this->trad->t('Caractéristiques Complémentaires'),
                        $this->router->generateUri(
                            'Reception.CreationBR.creatEdit',
                            ['order' => $initOrder, 'type' => $type, 'mode' => $mode, 'init' => 0, 'tab' => 'caracComp']
                        ),
                        1
                    );
                    break;

                case 'repartition':
                    ArianeSub::generate(
                        0,
                        4,
                        $this->trad->t('Répartition par lots'),
                        $this->router->generateUri(
                            'Reception.CreationBR.creatEdit',
                            ['order' => $initOrder, 'type' => $type, 'mode' => $mode, 'init' => 0, 'tab' => 'repartition']
                        ),
                        1
                    );
                    break;

                default:
                    break;
            }

            $subTitle = Trad::strBuild($this->trad->t('Bon de réception de la commande n°@1@'), $order);
            $heading = $this->trad->t('Entête du bon de réception') .
                ' - ' .
                Trad::strBuild(
                    $this->trad->t('Fournisseur @1@'),
                    ($orderDetails['RS'] == '' ? $this->trad->t('inconnu') : $orderDetails['RS'])
                ) .
                ' - ' .
                $this->trad->t('adresse') .
                ' - ' .
                $orderDetails['ADCDEFOU'] . ' ' . $orderDetails['VILCDEFO'];
            
            $registerMessage = $this->trad->t('Voulez-vous enregistrer ce bon de réception ?');
            $registerPopupTitle = $this->trad->t('Enregistrement de bon de réception');

            // pour vérifier que la date est supérieure ou inférieure à la date du jour
            $today = date('Ymd');

            $this->service->setSubArianeForResponse($order);

            return $this->renderer->render('@Reception/Creation/creatEdit', [
                'title'               => $this->trad->t('Réception'),
                'subTitle'            => $subTitle,
                'heading'             => $heading,
                'login'               => $_SESSION['Session_Login'],
                'detailOpen'          => $_SESSION['BR']['entete_crea_br_open'] ?? true,
                'onlyRal'             => $_SESSION['BR']['only_ral'] ?? true,
                'order'               => $initOrder,
                'type'                => $type,
                'mode'                => $mode,
                'br'                  => $br,
                'tab'                 => $tab,
                'droits'              => $this->droits,
                'receptionInitList'   => $receptionInit,
                'typeNumBR'           => $typeNumBR,
                'lines'               => $lineDetails ?? [],
                'documentsList'       => $documentsList ?? [],
                'incidentTypes'       => $incidentTypes ?? [],
                'incident'            => $incident ?? [],
                'initRecep'           => $_SESSION['BR']['init_recep'],
                'params'              => $this->params,
                'dateBL'              => $dateBL ?? '00000000',
                'datePer'             => $datePer ?? '00000000',
                'init'                => $init,
                'tooltipInit'         => $tooltipInit,
                'selectedLines'       => $selectedLines,
                'registerMessage'     => $registerMessage,
                'registerPopupTitle'  => $registerPopupTitle,

                // incidents
                'incidentLines'       => $incidentLines ?? [],

                // tab new doc
                'dateDuJour'          => Date::dateConverte($today),
                'tableau_pj'          => $docTypes ?? [],
                'docAtt'              => $docAtt ?? [],
                'idDoc'               => $idDoc ?? '',
                'NO_DA'               => 'BR_RECEP',
                'id'                  => $id,
                'post'                => $post,
                'code'                => $id,
                'pathEnregistrement'  => $pathEnregistrement ?? '',
                'nouveauDoc'          => true,
                'detail'              => true,
                'pathBack'            => $pathBack ?? '',
                'layout'              => '@ajax-layout/layout.twig',

                // caractéristiques complémentaires
                'additionalLines'     => $compLines,
                'noCcInfo'            => $noCcInfo,
                'idUserBasket'        => $_SESSION['id_user'],

                // répartition par lots
                'batchLines'          => $batchLines,
                'noBatchInfo'         => $noBatchInfo,

                // parametres
                'dateFormat'          => $_SESSION['DATE_FORMAT'],
                'today'               => $today,
            ]);

            // création de bon de retour
        } else {
            $brNumber = $order;
            ariane::setFocus($brNumber);
            if ($init === '1') {
                if ($mode == 'C') {
                    $brData = $this->service->initRetour($brNumber);
                    $initialBr = $brData[0];
                    $lineDetails = $brData[1];
                } else {
                    $initialBr = $this->serviceModif->resetOxaBrEnteteModif($brNumber);

                    // on initialise les paramètres enregistrés en session
                    $_SESSION['BR']['entete_crea_br_open'] = true;

                    // on supprime les fichiers dans tmp qui pourraient être restés lors d'une précédente création interrompue
                    $this->service->deleteTmpFiles();

                    $this->repositoryLot->resetOxaBrLigneLot();

                    // on initialise les lignes de oxa_br_ligne
                    $lineDetails = $this->serviceModif->resetOxaBrLigneModif($initialBr['NUM_BR_ANNULE'], $init, $type);
                }
            } else {
                $initialBr = $this->repository->getInfoBrEntete($_SESSION['Session_Login']);
                $lineDetails = $this->repository->getOxaBrLigne($_SESSION['Session_Login']);
            }

            if ($mode == 'C') {
                $ariane = $this->trad->t('Création bon de retour');
                $subTitle = Trad::strBuild($this->trad->t('Création d\'un bon de retour sur le BR n°@1@'), $brNumber);
            } else {
                $ariane = $this->trad->t('Modification bon de retour');
                $subTitle = Trad::strBuild($this->trad->t('Modification du bon de retour n°@1@ sur le BR n°@2@'), $brNumber, $initialBr['NUM_BR_ANNULE']);
            }

            Ariane::generate(2, $ariane);

            $orderDetails = $this->repository->orderDetails($initialBr['NUM_CDE'] ?? $initialBr['no_cde']);
            $heading = $this->trad->t('Entête du bon de retour') . ' - ' .
                Trad::strBuild(
                    $this->trad->t('Fournisseur @1@'),
                    ($orderDetails['RS'] == '' ? 'inconnu' : $orderDetails['RS'])
                ) . ' - ' .
                $this->trad->t('adresse') . ' - ' .
                $orderDetails['ADCDEFOU'] . ' ' .
                $orderDetails['VILCDEFO'];

            $registerMessage = $this->trad->t('Voulez-vous enregistrer ce bon de retour ?');
            $registerPopupTitle = $this->trad->t('Enregistrement de bon de retour');

            $lineDetails = $this->serviceLot->getBatchReturn(($initialBr['NUM_BR'] ?? $initialBr['NUM_BR_ANNULE']), $lineDetails);

            return $this->renderer->render('@Reception/Creation/creatEditReturn', [
                'title'                 => $this->trad->t('Réception'),
                'subTitle'              => $subTitle,
                'orderDetails'          => $orderDetails,
                'heading'               => $heading,
                'login'                 => $_SESSION['Session_Login'],
                'detailOpen'            => $_SESSION['BR']['entete_crea_br_open'] ?? true,
                'onlyRal'               => $_SESSION['BR']['only_ral'] ?? true,
                'order'                 => $order,
                'type'                  => $type,
                'mode'                  => $mode,
                'initialBr'             => $initialBr,
                'tab'                   => $tab,
                'droits'                => $this->droits,
                'lines'                 => $lineDetails,
                'params'                => $this->params,
                'datePer'               => \date('Ymd'),
                'init'                  => $init,
                'registerMessage'       => $registerMessage,
                'registerPopupTitle'    => $registerPopupTitle,
                'idUserBasket'          => $_SESSION['id_user'],
                'returnAll'             => $_SESSION['BR']['returnAll'] ?? 'false',
            ]);
        }
    }

    public function ajaxUpdateHeadingAction(): Response
    {
        $post = $this->request->getParsedBody();
        $type = $this->request->getAttribute('type');
        // si le champs à mettre à jour est un CS
        if (\strpos($post['field'], 'CS_EXTENTION') === 0) {
            $spliter = Constante::spliter;
            $cs = \explode($spliter, $post['field']);

            $this->csManager->updateChampSupp('BR_OXAPROC', $_SESSION['Session_Login'], $cs[3], $post['value'], $this->pdo);
        } else {
            $this->service->updateOxaBrEntete($post['field'], $post['value'], $this->params);
        }

        $br = $this->repository->getInfoBrEntete($_SESSION['Session_Login']);
        if (empty($br)) {
            LogSysteme::prefixErrorLog('Missing br info for "'.$_SESSION['Session_Login'].'"');
            return new Response(404, [], 'Missing BR');
        }

        // TODO : split into 2
        if ($type == 'R') {
            $receptionInit = [
                'NO_INIT'   => $this->trad->t('Pas d\'initialisation'),
                'SOLDE'     => $this->trad->t('Réception du solde'),
                'ECHUE'     => $this->trad->t('Réception échue'),
            ];

            $tooltipInit = $this->trad->t('Attention : en changeant l\'initialisation, vous remettrez à zéro ce bon de réception');

            $orderDetails = $this->repository->orderDetails($br['no_cde']);
            $heading = $this->trad->t('Entête du bon de réception') . ' - ' . Trad::strBuild($this->trad->t('Fournisseur @1@'), ($orderDetails['RS'] == '' ? 'inconnu' : $orderDetails['RS'])) . ' - ' . $this->trad->t('adresse') . ' - ' . $orderDetails['ADCDEFOU'] . ' ' . $orderDetails['VILCDEFO'];

            return new Response(200, [], (string)json_encode([
                'heading' => $this->renderer->render('@Reception/Creation/heading', [
                    'br'                  => $br,
                    'detailOpen'          => $_SESSION['BR']['entete_crea_br_open'] ?? true,
                    'heading'             => $heading,
                    'params'              => $this->params,
                    'initRecep'           => $_SESSION['BR']['init_recep'],
                    'receptionInitList'   => $receptionInit,
                    'tooltipInit'         => $tooltipInit,
                    'onlyRal'             => $_SESSION['BR']['only_ral'] ?? true,
                ]),
            ]));
        }

        return new Response(200, [], (string)json_encode([
            'heading' => $this->renderer->render('@Reception/Creation/headingReturn', [
                'initialBr'   => $br,
                'detailOpen'  => $_SESSION['BR']['entete_crea_br_open'] ?? true,
                'params'      => $this->params,
            ]),
        ]));
    }

    public function ajaxCommentaireAction(): string
    {
        $order      = $this->request->getAttribute('order');
        $type       = $this->request->getAttribute('type');
        $mode       = $this->request->getAttribute('mode');
        $line       = $this->request->getAttribute('line');

        return $this->renderer->render('@Reception/Creation/Popup/commentaire', [
            'commentaire' =>
                $this->repository->getOxaBrLigne(
                    $_SESSION['Session_Login'],
                    $line
                )['COMMENT'] ?? '',
            'order' => $order,
            'type' => $type,
            'mode' => $mode,
            'line' => $line,
        ]);
    }

    public function saveCommentAction(): Response
    {
        $post       = $this->request->getParsedBody();
        $order      = $this->request->getAttribute('order');
        $type       = $this->request->getAttribute('type');
        $mode       = $this->request->getAttribute('mode');
        $line       = $this->request->getAttribute('line');

        $validator = $this->createValidator();
        $validator->isStringAvecEspace($this->trad->t('Commentaire'), $post['commentaire'], 0, 3000);

        if ($validator->isValid()) {
            (new OxaBrLigne($this->pdo))->update(['COMMENT' => $post['commentaire']], ['login' => $_SESSION['Session_Login'], 'no_ligne_br' => $line]);
        }

        return new Response(200, [], (string)json_encode([
            'path' => $this->router->generateUri(
                'Reception.CreationBR.creatEdit',
                ['order' => $order, 'type' => $type, 'mode' => $mode, 'init' => '0']
            )
        ]));
    }

    public function ajaxUpdateLineAction(): Response
    {
        $post       = $this->request->getParsedBody();
        $order      = $this->request->getAttribute('order');
        $type       = $this->request->getAttribute('type');
        $mode       = $this->request->getAttribute('mode');

        $explode    = explode('-', $post['field']);
        $field      = $explode[0];
        $line       = $explode[1] ?? null;

        // validator oxa_br_ligne
        // attention aux contrôles sur les dates, et sur les input switch
        // on contrôle que la quantité réceptionnée ou le montant réceptionné n'excèdent pas le reste à livrer
        
        if (!$this->validator->isValid()) {
            return new Response(443, [], (string) \json_encode([
                'responseText'  => $this->validator->getError(),
                'title'         => $this->trad->t('Erreur')
            ]));
        } else {
            if ($field == 'returnAll') {
                // $listeLigneBR = (new OxaBrLigne($this->pdo))->fetchAll(['no_ligne_br'], ['filter_login' => $_SESSION['Session_Login']]);
                $this->repository->updateOxaBrLigneReturn($post['value']);
                // $field = 'IS_ANNULE';
                // foreach ($listeLigneBR as $ligneBR) {
                //     $this->service->updateOxaBrLigne($ligneBR['no_ligne_br'], $field, $post['value']);
                // }
                $lines = null;
            } else {
                $this->service->updateOxaBrLigne($line, $field, $post['value']);
                $lines = $this->repository->getOxaBrLigne($_SESSION['Session_Login']);
            }

            if ($type == 'R') {
                // on vérifie que la pastille sur le subariane incidents doit toujours être affichée
                // on récupère les lignes qui nécessitent une répartition par lots et sont en réception
                $batchLines = $this->serviceLot->getBatchLines();

                if (!empty($batchLines)) {
                    ArianeSub::generate(
                        0,
                        4,
                        $this->trad->t('Répartition par lots'),
                        $this->router->generateUri('Reception.CreationBR.creatEdit', ['order' => $order, 'type' => $type, 'mode' => $mode, 'init' => 0, 'tab' => 'repartition']),
                        0,
                        [],
                        'sub_batch',
                        '',
                        '',
                        ''
                    );
                }

                $this->service->setSubArianeForResponse($order);
                
                return new Response(200, [], (string)json_encode([
                    'lines' => $this->renderer->render('@Reception/Creation/Tabs/lines', [
                        'lines'   => $lines,
                        'droits'  => $this->droits,
                        'params'  => $this->params,
                        'order'   => $order,
                        'type'    => $type,
                        'mode'    => $mode,
                        'init'    => 0,
                        'onlyRal' => $_SESSION['BR']['only_ral'] ?? true
                    ]),
                    'subAriane' => $this->renderer->render('@Reception/Creation/arianeSub')
                ]));
            } else {
                $lineDetails = $this->repository->getOxaBrLigne($_SESSION['Session_Login']);
                $lineDetails = $this->serviceLot->getBatchReturn($order, $lineDetails, $mode);

                $initialBr = $this->repository->getInfoBrEntete($_SESSION['Session_Login']);
    
                // $batchReturn = $this->service->get
                return new Response(200, [], (string)json_encode([
                    'lines' => $this->renderer->render('@Reception/Creation/Tabs/linesReturn', [
                        'lines'       => $lineDetails,
                        'droits'      => $this->droits,
                        'params'      => $this->params,
                        'order'       => $order,
                        'type'        => $type,
                        'mode'        => $mode,
                        'init'        => 0,
                        'initialBr'   => $initialBr
                    ]),
                ]));
            }
        }
    }

    public function ajaxUpdateCCAction(): Response
    {
        $post       = $this->request->getParsedBody();

        $ccToUpdate = (new CCLDoc($this->pdo))->find([
            'DOC_TYPE'          => 'BRT',
            'DOC_NUM'           => 0,
            'DOC_LINE_NUM'      => $post['line'],
            'ID_USER_BASKET'    => $_SESSION['id_user'],
            'CC_ID'             => $post['id']
        ]);

        if ($ccToUpdate) {
            if ($ccToUpdate['CC_TYPE'] === 'LOGIQUE') {
                $post['value'] = Sql::convertBooleenCheckboxForWsdl($post['value']);
            }

            if ($ccToUpdate['CC_TYPE'] === 'DATE') {
                Date::dateToSql($post['value']);
            }

            if ($ccToUpdate['CC_TYPE'] === 'HEURE') {
                $post['value'] = str_replace(':', '', $post['value']);
            }

            (new CaracCompl($this->pdo))->updateCC(
                $post['value'],
                'BRT',
                0,
                $post['line'],
                $_SESSION['id_user'],
                $post['id']
            );
        }

        return new Response();
    }

    /**
     * ajaxUpdateSessionAction
     *
     * @return Response
     */
    public function ajaxUpdateSessionAction(): Response
    {
        $post = $this->request->getParsedBody();

        $_SESSION['BR']['entete_crea_br_open'] = false;
        $_SESSION['BR']['only_ral'] = $post['ral'];

        if ($post['open']) {
            $_SESSION['BR']['entete_crea_br_open'] = ($post['open'] == 'true');
        }

        return new Response();
    }

    public function ajaxDownloadDocAction(): string
    {
        $id = $this->request->getAttribute('id');
        $ordre = $this->request->getAttribute('ordre');

        $document = $this->service->getInfoDoc($ordre);

        return Fichier::UploadClient((new ParseBase1())->getRep()->tmp . $document['NEW_NAME'], $document['NOM_ORI']);
    }

    public function ajaxDeleteDocAction(): Response
    {
        $ordre = $this->request->getAttribute('ordre');
        $this->service->deleteDoc($ordre);
        return new Response();
    }

    /**
     * saveDocAction
     *
     * @return Response
     */
    public function saveDocAction(): Response
    {
        $post   = $this->request->getParsedBody();
        $id     = $this->request->getAttribute('id');
        $idDoc  = $this->request->getAttribute('idDoc') ?? '';
        $mode   = $this->repository->getInfoBrEntete($_SESSION['Session_Login'], 'MODE')['MODE'] == '' ? 'C' : 'M';

        $this->service->saveDoc($post, $idDoc);

        return $this->redirect('Reception.CreationBR.creatEdit', ['order' => $id, 'type' => 'R', 'mode' => $mode, 'init' => 0, 'tab' => 'documents']);
    }

    public function validateAction(): Response
    {
        $type   = $this->request->getAttribute('type');
        $mode   = $this->request->getAttribute('mode');
        $confirm = $this->request->getAttribute('confirm');
        $brEntete = $this->repository->getInfoBrEntete($_SESSION['Session_Login']);
        $validator = $this->createValidator();

        if ($type == 'R' && $confirm === 'true') {
            // si on vient de la popup de confirmation, le post est égal aux infos enregistrées dans oxa_br_entete
            $post               = $brEntete;
            $spliter            = Constante::spliter;
            $CS                 = new ChampSupp($this->pdo);
            $brCsList           = $CS->listeCSDON('BR_OXAPROC', $_SESSION['Session_Login'], $this->pdo);
            $post['date_bl']    = Date::dateConverte($post['date_bl']);
            $post['DATE_PER']   = Date::dateConverte($post['DATE_PER']);

            foreach ($brCsList as $value) {
                $post['CS_EXTENTION' . $spliter . 'BR_RECEP' . $spliter . $_SESSION['Session_Login'] . $spliter . $value['NUM_FIX']] = $value['VALEUR'];
            }
        } else {
            $post = $this->request->getParsedBody();
        }

        /**************************************** Contrôles entête ****************************************/

        // on récupère le numéro de BR
        if ($brEntete['no_br'] == '0' && $this->params['MODE_NUM'] == 'M') {
            if ($this->params['MODE_NUM'] == 'M') {
                $validator->setError($this->trad->t('Le n° de bon de réception est obligatoire.'));
            }
        }

        // contrôles spécifiques aux bons de réception
        if ($type == 'R') {
            if ($this->params['BL_OBLIG'] === true) {
                $validator->isStringAvecEspace(
                    $this->trad->t('N° de bon de Livraison'),
                    $post['no_bl'],
                    1,
                    60
                );
            }

            $dateBl = Date::dateConverte($brEntete['date_bl']);
            
            $validator->isDate(
                $dateBl,
                '',
                '',
                $this->params['DATE_BL_OBLIG'] === true ? false : true,
                $this->trad->t('Date du bon de livraison')
            );
        }

        // contrôles CS
        $validator->validatorCS('BR_RECEP', $_SESSION['Session_Login'], $post, $this->pdo, '', 0, 'BR_OXAPROC');

        if (!isset($post['DATE_PER'])) {
            $post['DATE_PER'] = Date::dateConverte($brEntete['DATE_PER']);
        }

        $validator->isDate(
            $post['DATE_PER'],
            '',
            '',
            false,
            $this->trad->t('Date de période')
        );

        if ($type ==  'R') {
            // contrôles spécifiques aux bons de réception

            // on vérifie qu'au moins une ligne a été sélectionnée pour le BR
            $brLines = $this->repository->getOxaBrLigne($_SESSION['Session_Login']);

            $linesSelected = 0;
            foreach ($brLines as $line) {
                if (Sql::toBool($line['is_reception'])) {
                    $linesSelected += 1;

                    if ($line['qte_a'] > $line['qte_c']) {
                        $validator->setError($this->trad->t('La quantité acceptée ne peut pas être supérieure à la quantité comptée.'));
                    }

                    if ($line['qte_c'] > $line['qte_r']) {
                        $validator->setError($this->trad->t('La quantité comptée ne peut pas être supérieure à la quantité reçue.'));
                    }

                    if (Sql::toBool($line['EN_MNT'])) {
                        if ($line['MNT_REC'] <= 0) {
                            $validator->setError($this->trad->t('Le montant retourné doit être supérieur à 0.'));
                        }
                    } else {
                        if ($line['qte_r'] <= 0) {
                            $validator->setError($this->trad->t('La quantité reçue doit être supérieure à 0.'));
                        }
                    }

                    // contrôles CC de la ligne
                    $post['saveValidatorCC'] = '{"init":null,"typeDoc":"BRT","idDoc":0,"idLigne":"'
                        . $line['no_ligne_cde'] . '","idPanier":"' . $_SESSION['id_user'] . '"}';
                    $validator->validatorCC($this->pdo, $post);
                }
            }

            if ($linesSelected == 0) {
                $validator->setError($this->trad->t('Veuillez sélectionner au moins une ligne à réceptionner.'));
            }
        } else {
            // contrôles spécifiques aux bons de retour

            // on vérifie qu'au moins une ligne a été sélectionnée pour le BR
            $brLines = $this->repository->getOxaBrLigne($_SESSION['Session_Login']);
            $linesSelected = 0;

            foreach ($brLines as $line) {
                if ($line['IS_ANNULE'] === '1') {
                    $linesSelected += 1;

                    if ($line['QTE_ANNULE'] > $line['qte_a']) {
                        $validator->setError($this->trad->t('La quantité retournée ne peut pas être supérieure à la quantité acceptée.'));
                    }

                    if (Sql::toBool($line['EN_MNT'])) {
                        if ($line['MNT_RET'] <= 0) {
                            $validator->setError($this->trad->t('Le montant retourné doit être supérieur à 0.'));
                        }
                    } else {
                        if ($line['QTE_ANNULE'] <= 0) {
                            $validator->setError($this->trad->t('La quantité retournée doit être supérieure à 0.'));
                        }
                    }
                }
            }

            if ($linesSelected == 0) {
                $validator->setError($this->trad->t('Veuillez sélectionner au moins une ligne à retourner.'));
            }
            
            // contrôles relatifs aux répartitions par lots
            $brLines = $this->serviceLot->getBatchReturn($brEntete['NUM_BR_ANNULE'], $brLines);
            $errorBatch = $this->serviceLot->checkDistributionForValidation($brLines);
            
            // on vérifie que la répartition correspond à la quantité acceptée/retournée si répartition par lots
            if ($errorBatch != '') {
                $validator->setError($errorBatch);
            }
        }

        if (!$validator->isValid()) {
            return new Response(200, [], $this->renderer->render('@popup-erreur/ErreurCreation', [
                'ErreurValid'    => $validator->getError(),
            ]));
        }

        /**************************************** Enregistrement BDD ****************************************/

        // si le numéro de BR n'est pas renseigné, ou en attribue un
        if ($brEntete['no_br'] == '0') {
            $brEntete['no_br'] = $this->service->setBrNumber();
        }

        // si on est en mode modif, on commence par supprimer les données de BR_LIGNE, SBR_LOTS, DOC_ATT et CC_LDOC WHERE DOC_TYPE = 'BR' et DOC_NUM = $brNumber
        if ($mode == 'M') {
            $brRecep = new BrRecep($this->pdo);
            $brRecep->delete(['NUM_BR' => $brEntete['no_br']]);
            $brLigne = new BrLigne($this->pdo);
            $brLigne->delete(['NUM_BR' => $brEntete['no_br']]);
            $sbrLots = new SbrLots($this->pdo);
            $sbrLots->delete(['NO_BR' => $brEntete['no_br']]);

            if ($type == 'R') {
                // suppression des docs du BR initial
                $this->service->deleteDocBrBeforeSaving($brEntete['no_br']);

                $ccLdoc = new CCLDoc($this->pdo);
                $ccLdoc->delete(['DOC_TYPE' => 'BR', 'DOC_NUM' => $brEntete['no_br']]);
            }
        }

        // on commence par enregistrer en bdd les données du BR en cours de création
        $validation = $this->service->saveBr();

        // enregistrement CS_DON : COD_TAB = 'BR_OXAPROC' => 'BR_RECEP'
        $this->repository->saveCsBr($validation);

        // on enregistre les répartitions par lots si les articles du BR sont concernés
        if (!empty($this->serviceLot->getBatchLines())) {
            $this->serviceLot->saveBatchDistribution($validation, $type);
        }

        if ($type == 'R') {
            // on enregistre les documents rattachés
            $this->service->saveDocBr($validation);

            // on enregistre les CC dont le DOC_TYPE est BRT vers la table CC_LDOC où DOC_TYPE = 'BR'
            $this->service->saveCcBr();

            // enregistrement incidents + envoi mail
            $incident = $this->incidentService->getIncident();
            $lineIncidents = $this->incidentService->getIncidentLines($brEntete['no_cde'], true);
            if (!empty($incident) || !empty($lineIncidents)) {
                // on enregistre l'incident dans la table FOURNINC
                $this->incidentService->setSupplierIncident($validation, $incident, $lineIncidents, $this->params);
            }
        }

        // on enregistre l'évènement d'enregistrement du BR dans la table BR_EVENT et dans la table CA_EVENT
        $this->service->saveEventCreation(
            $validation,
            $brEntete['no_cde'],
            $type,
            $brEntete['NUM_BR_ANNULE']
        );

        /**************************************** Vérif et validation via WSDL ****************************************/
        // si on a le droit de validation BR
        if ($this->droits['HA_BR_VAL']) {
            // on fait appel au WSDL de vérif et validation
            $wsdl = $this->wsdlManager->valDevalSuppBr('V', $validation);
            $returnWsdl = new SimpleXMLElement($wsdl->responseData);
    
            if ($returnWsdl->Statut == 'E') {
                // si la réponse du wsdl est une erreur, on passe en modification du BR créé
                $path = $this->router->generateUri('Reception.CreationBR.creatEdit', ['order' => $validation, 'type' => $type, 'mode' => 'M', 'init' => 1]);
    
                return new Response(200, [], $this->renderer->render('@popup-erreur/confirmationRedirection', [
                    'iconePopup' => 'information',
                    'message' => $returnWsdl->MsgErreur ?? '',
                    'pathURL' => $path,
                    'cancel' => true,
                    'titre' => $this->trad->t('Erreur validation')
                ]));
            }
        }

        // on réinitialise alors les données de oxa_br_entete, oxa_br_ligne et oxa_br_ligne_lots
        $this->repository->deleteOxaBrEntete($_SESSION['Session_Login']);
        $this->repository->deleteOxaBrLigne($_SESSION['Session_Login']);
        $this->repositoryLot->resetOxaBrLigneLot();

        // si la réponse du wsdl est ok, on donne le numéro de BR créé et on renvoie vers l'index de création de BR
        $backUrl = Ariane::getBackPath();
        $backPost = Ariane::getBackPost();

        // s'il s'agit d'une réception et non d'un retour
        if ($type == 'R') {
            // on vérifie si la commande est soldée ou non
            $order = $this->service->getOrderFromBr((string)$validation);

            if (!(new CreationBR($this->pdo))->isOrderSettled((string)$validation)) {
                /* si certaines lignes de la commande ont toujours un reste à livrer, on propose de solder manuellement la commande
                si l'utilisateur en a le droit */
                $continuePath = $this->router->generateUri('Commande.solderCommande.physiquement', ['idCommande' => $order]);
        
                if ($this->droits['HA_CA_SPM'] == 1) {
                    return new Response(200, [], $this->renderer->render('@Reception/Creation/Popup/settleOrderConfirmation', [
                        'message' => Trad::strBuild($this->trad->t('Le BR n°@1@ a été créé avec succès.'), $validation)
                            . '</br></br>'
                            . Trad::strBuild(
                                $this->trad->t(
                                    'La commande @1@ n\'est pas soldée physiquement par cette réception. Souhaitez-vous accéder à l\'écran de gestion du solde manuel du reliquat de la commande ?'
                                ),
                                $order
                            ),
                        'continuePath' => $continuePath,
                        'returnPath' => $backUrl,
                        'titrePopup' => $this->trad->t('Avertissement')
                    ]));
                }
            }
        }

        return new Response(200, [], $this->renderer->render('@popup-erreur/confirmationRedirection', [
            'iconePopup' => 'information',
            'message' => Trad::strBuild($this->trad->t('Le BR n°@1@ a été créé avec succès.'), $validation),
            'pathURL' => $backUrl,
            'postURL' => json_encode($backPost),
            'titre' => ($type == 'R'
                ? $this->trad->t('Bon de réception enregistré')
                : $this->trad->t('Bon de retour enregistré'))
        ]));
    }
}
