<?php
namespace Modules\Commande\Controller;

use Entity\Model\CaEntet;
use Entity\Model\CaEvent;
use Entity\Model\Docatt;
use Entity\Model\Fourniss;
use Entity\Model\Hastutil;
use Entity\Model\Memos;
use Entity\Model\TpEvt;
use GuzzleHttp\Psr7\Response;
use Helpers\Ariane\Ariane;
use Helpers\Log\LogSysteme;
use Helpers\Fichier\Fichier;
use Helpers\Outil\Roles;
use Helpers\Outil\Sql;
use Helpers\Validator\Validator;
use Modules\Commande\Repository\TermPaieRepo;
use Psr\Container\ContainerInterface;
use Modules\Commande\Service\AccRecepService;
use Modules\GlobalApplication\WebService\DocRattaches;
use Skeleton\Controller\Controller;
use Skeleton\Renderer\RendererInterface;
use Skeleton\Router;

/**
 * @see \Modules\Commande\Rules\AccRecep
 */
class AccRecepController extends Controller
{

    /**
     * @var AccRecepService $AccRecepService
     */
    public $AccRecepService;

    public function __construct(RendererInterface $renderer, \PDO $pdo, Router $router, ContainerInterface $contenaire)
    {
        parent::__construct($renderer, $pdo, $router, $contenaire);
    
        $this->AccRecepService = new AccRecepService($this->getTranslationService(), $pdo, $router);
    }
    
    public function formCreationAction() : string
    {
        $commandeId = $this->request->getAttribute('commandeId');
        $trad = $this->getTranslationService();

        $commande = (new CaEntet($this->pdo))->find($commandeId);
        if ($commande == null) {
            throw new \Exception('Invalid commande #'.$commandeId);
        }
        $commande['Fourniss'] = (new Fourniss($this->pdo))
            ->find($commande['CODE_FOU']);
        
        Ariane::generate(1, $trad->t('Enregistrer un Accusé Réception'));

        return $this->renderer->render(
            '@Commande/AccRecep/AccRecepFormCreation',
            [
                'commandeId' => $commandeId,
                'commande' => $commande,
                'form' => [
                    'listField' => $this->AccRecepService->getFormCommonField([
                        'DTE_AR' => date('Ymd'),
                    ]),
                ],
            ],
        );
    }

    public function createAction() :Response
    {
        $trad = $this->getTranslationService();
        $post = $this->request->getParsedBody();
        $commandeId = $this->request->getAttribute('commandeId');
        $entityCommand = new CaEntet($this->pdo);
        $commande = $entityCommand->find($commandeId);
        $file = $this->request->getUploadedFiles();
        $trad = $this->getTranslationService();
        
        if (empty($commande)
            || $commande['ETAT_CDE'] != 'E'
            || $commande['DTE_AR'] != '00000000'
        ) {
            LogSysteme::prefixErrorLog((new \Exception('Attempt to save AccRecep on invalid commande "'.$commandeId.'"'))->__toString());
            return $this->create404Response();
        }
        
        //___________________
        // Validation

        $validator = $this->createValidator();
        $validator->isDate(
            $post['DTE_AR'],
            '',
            date('Ymd'),
            false,
            $trad->t('date d’accusé réception')
        );
        $validator->isCheck($post['AR_NCONF']);
        $validator->isStringSansEspace(
            $trad->t('Référence AR fournisseur'),
            $post['AR_REF'] ?? '',
            3,
            30
        );

        $validator->isStringAvecEspace(
            $trad->t('Commentaire'),
            $post['MEMO'] ?? '',
            0,
            3000
        );

        $file_name = $this->AccRecepService->validateFile($validator, $file);

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

        //___________________
        // Creation

        if (!$this->pdo->beginTransaction()) {
            throw new \Exception('!!!');
        }

        $entityCommand->update(
            [
                'DTE_AR' => $post['DTE_AR'],
                'AR_NCONF' => Sql::boolSql2($post['AR_NCONF']),
                'AR_REF' => $post['AR_REF'],
            ],
            $commande['NO_CDE']
        );
        
        $memoId = 0;
        if (!empty($post['MEMO'])) {
            $memoId = Sql::updateMemo($this->pdo, '', $post['MEMO']);
        }

        (new CaEvent($this->pdo))->insertEntity(
            $commande['NO_CDE'],
            $commande['AVENANT'],
            'SAR',
            $_SESSION['Session_Login'],
            (string)$memoId
        );
        
        if ($file_name !== null) {
            $newPath = Fichier::UploadDocAtt($file_name);
            $file['import_attached_file']->moveTo(
                $newPath['racine'] . $newPath['new_name']
            );
            $xmlResult = (new DocRattaches())->NouveauDocAtt([
                'langue' => $_SESSION['Session_Langue'],
                'new_name' => $newPath["new_name"],
                'file_name' => $file_name,
                'typeObjet' => 'CA_ENTET',
                'refObjet' => str_pad($commande['NO_CDE'], 9, '0', STR_PAD_LEFT),
                'typePj' => 'ARF',
                'titreDoc' => $trad->t('Accusé de réception Commande'),
                'auteur' => $_SESSION['Session_Login'],
                'centre' => $_SESSION['Session_CodeCtrEmetteur'],
                'dateParu' => $post['DTE_AR'],
                'dateVali' => '00000000',
                'PJCommande' => 1,
                'commentaire' => '',
            ]);

            $xmlResult = new \SimpleXMLElement($xmlResult->responseData);

            if ($xmlResult->Statut != 'O') {
                $this->pdo->rollBack();
                return new Response(400, [], $this->renderer->render(
                    '@popup-erreur/ErreurCreation',
                    [ 'ErreurValid' => $xmlResult->MsgErreur ]
                ));
            }
        }

        (new TpEvt($this->pdo))->update(
            ['EVT_OK' => true],
            [
                'NUM_CDE' => $commande['NO_CDE'],
                'EVENEMENT' => 'SAR',
            ]
        );

        (new TermPaieRepo($this->pdo))->recalc($commande['NO_CDE']);

        if (!$this->pdo->commit()) {
            throw new \Exception('!!!');
        }

        // Success
        return $this->createJsonResponse([
            'suggestAvenantCreation' => $post['AR_NCONF'],
        ]);
    }

    /**
     * @return Response|string
     */
    public function detailAction()
    {
        $commandeId = $this->request->getAttribute('commandeId');

        //_____________________________
        // Load data

        $commande = $this->AccRecepService->getAccRecept($commandeId);

        if ($commande === null) {
            return $this->create404Response();
        }

        $droit = Roles::droitsUtilMulti($this->pdo, [
            'HA_CA_SAR',
            'HA_CA_MAR',
        ]);

        //_____________________________
        // Render
        
        return $this->renderer->render(
            '@Commande/AccRecep/AccRecepPopupDetail',
            [
                'commandeId' => $commandeId,
                'accRecep' => [
                    'DTE_AR' => $commande['DTE_AR'],
                    'AR_REF' => $commande['AR_REF'],
                    'AR_NCONF' => $commande['AR_NCONF'],
                    'MEMO' => $commande['AccRecep']['Memo']['CONTMEMO'] ?? '',
                    'DocAtt' => $commande['AccRecep']['DocAtt'],
                ],
                'canUpdateAccRecep' =>
                    $droit['HA_CA_SAR']
                    && $droit['HA_CA_MAR']
                    && $commande['DTE_AR'] != '00000000',
            ],
        );
    }

    /**
     * @return Response|string
     */
    public function formUpdateAction()
    {
        $commandeId = $this->request->getAttribute('commandeId');
        $trad = $this->getTranslationService();

        //_____________________________
        // Load data

        $commande = $this->AccRecepService->getAccRecept($commandeId);

        if ($commande === null) {
            return $this->create404Response();
        }

        $commande['Fourniss'] = (new Fourniss($this->pdo))
            ->find($commande['CODE_FOU']);

        //_____________________________
        // Render

        Ariane::generate(1, $trad->t('Modifier l’Accusé réception'));

        return $this->renderer->render(
            '@Commande/AccRecep/AccRecepFormUpdate',
            [
                'commandeId' => $commandeId,
                'commande' => $commande,
                'form' => [
                    'listField' => $this->AccRecepService->getFormCommonField($commande),
                ],
            ],
        );
    }

    public function updateAction() :Response
    {
        $post = $this->request->getParsedBody();
        $commandeId = $this->request->getAttribute('commandeId');
        $entityCommand = new CaEntet($this->pdo);
        $commande = $entityCommand->find($commandeId);
        $file = $this->request->getUploadedFiles();
        $trad = $this->getTranslationService();
        
        if (empty($commande) || $commande['DTE_AR'] == '00000000') {
            LogSysteme::prefixErrorLog((new \Exception('Attempt to update AccRecep on invalid commande "'.$commandeId.'"'))->__toString());
            return $this->create404Response();
        }
        
        //___________________
        // Validation

        $validator = $this->createValidator();

        $this->AccRecepService->validateAccRecept($validator, $post);
        $file_name = $this->AccRecepService->validateFile($validator, $file);

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

        //___________________
        // Update AccRecept

        if (!$this->pdo->beginTransaction()) {
            throw new \Exception('!!!');
        }

        $entityCommand->update(
            [
                'DTE_AR' => $post['DTE_AR'],
                'AR_NCONF' => Sql::boolSql2($post['AR_NCONF']),
                'AR_REF' => $post['AR_REF'],
            ],
            $commande['NO_CDE']
        );

        if (! empty($post['MEMO'])) {
            //!\ Note : There may be multiple event SAR for one AR in which case we take the most recent

            // Get last event
            $caEvent = new CaEvent($this->pdo);
            $event = $caEvent->findAll(
                [
                    'NO_CDE' => $commande['NO_CDE'],
                    'AVNT' => $commande['AVENANT'],
                    'CODE' => 'SAR',
                ],
                [],
                [ 'tri_NUM_ORD' => 'DESC' ]
            ) [0] ?? null;

            $idMemo = Sql::updateMemo($this->pdo, $event['NM_COMME'], $post['MEMO']);
            
            

            $caEvent->update([
                'NM_COMME' => $idMemo
            ], [
                'NO_CDE' => $commande['NO_CDE'],
                'AVNT' => $commande['AVENANT'],
                'NUM_ORD' => $event['NUM_ORD'],
            ]);
        }
        
        if ($file_name !== null) {
            $infoDoc = (new Docatt($this->pdo))->find([
                'NO_DA' => 'CA_ENTET',
                'COD_ENR' => str_pad($commande['NO_CDE'], 9, '0', STR_PAD_LEFT),
                'TYPE_PJ' => 'ARF'
            ]);

            // Replace previous doc
            $newPath = Fichier::UploadDocAtt($file_name);
            $file['import_attached_file']->moveTo(
                $newPath['racine'] . $newPath['new_name']
            );
            $xmlResult = (new DocRattaches())->ModificationDocAtt([
                'langue' => $_SESSION['Session_Langue'],
                'new_name' => $newPath["new_name"],
                'file_name' => $file_name,
                'typeObjet' => 'CA_ENTET',
                'refObjet' => str_pad($commande['NO_CDE'], 9, '0', STR_PAD_LEFT),
                'typePj' => 'ARF',
                'titreDoc' => $trad->t('Accusé de réception Commande'),
                'auteur' => $_SESSION['Session_Login'],
                'centre' => $_SESSION['Session_CodeCtrEmetteur'],
                'dateParu' => $post['DTE_AR'],
                'dateVali' => '00000000',
                'PJCommande' => 1,
                'commentaire' => '',
                'numOrdre' => $infoDoc['NO_ORDRE'], // Assume it is 1
            ]);

            $xmlResult = new \SimpleXMLElement($xmlResult->responseData);

            if ($xmlResult->Statut != 'O') {
                $this->pdo->rollBack();
                return new Response(400, [], $this->renderer->render(
                    '@popup-erreur/ErreurCreation',
                    [ 'ErreurValid' => $xmlResult->MsgErreur ]
                ));
            }
        }

        if (!$this->pdo->commit()) {
            throw new \Exception('!!!');
        }

        // Success
        return $this->createJsonResponse([
            'suggestAvenantCreation' => $post['AR_NCONF'],
        ]);
    }


    public function popupCreateAvenantAction() : string
    {
        $numCde = $this->request->getAttribute('commandeId');
        return $this->renderer->render('@Commande/GestionCommande/popupAvenant', [
            'idCommande' => $numCde,
            'cancel' => [
                'route' => 'ariane',
                'path' => Ariane::getBackPath(),
                'post' => Ariane::getBackPost(),
                'label' => 'Ignorer',
            ],
            'success' => [
                'route' => 'ariane',
                'path' => Ariane::getBackPath(),
                'post' => Ariane::getBackPost(),
            ],
        ]);
    }
}
