<?php

namespace Modules\ProjetAchat\Controller;

use GuzzleHttp\Psr7\Response;
use Helpers\Ariane\Ariane;
use Helpers\Trad\Trad;
use Modules\ProjetAchat\Service\CategorieService;
use Modules\ProjetAchat\Service\DonneeService;
use Psr\Container\ContainerInterface;
use Skeleton\Controller\Controller;
use Skeleton\Renderer\RendererInterface;
use Skeleton\Router;
use Tamtamchik\SimpleFlash\Flash;
use Modules\ProjetAchat\Repository\BibliothequeDonnee;
use Modules\ProjetAchat\Service\ModeleProjetService;

class DonneeController extends Controller
{
    /**
     * @var Flash $flash
     */
    private $flash;

    /**
     * @var CategorieService $categoryService
     */
    private $categoryService;

    /**
     * @var DonneeService $dataService
     */
    private $dataService;


    /**
     * @var BibliothequeDonnee $bibliotheque
     */
    private $bibliotheque;

    /**
     * DonneeController constructor.
     * @param RendererInterface $renderer
     * @param \PDO $pdo
     * @param Router $router
     * @param ContainerInterface $contenaire
     */
    public function __construct(RendererInterface $renderer, \PDO $pdo, Router $router, ContainerInterface $contenaire)
    {
        parent::__construct($renderer, $pdo, $router, $contenaire);
        $this->flash = new Flash();
        $this->categoryService = new CategorieService($this->pdo);
        $this->dataService = new DonneeService($this->pdo);
        $this->bibliotheque = new BibliothequeDonnee($this->pdo);
    }

    /**
     * @return Response|string
     */
    public function createAction()
    {
        $typeObjet = $this->request->getAttribute('typeObjet');
        $idObjet = $this->request->getAttribute('idObjet');
        $idCategorie = $this->request->getAttribute('idCategorie');
        $trad = $this->getTranslationService();
        
        $post = $this->request->getParsedBody();

        if ($post) {
            $validator = $this->validateData($post);
            
            $validator->isTrue($this->bibliotheque->valeurDataExiste($typeObjet, $idObjet, $idCategorie, 'NOMSQLDW', $post['NOMSQLDW']), $trad->t('Le nom de Table OXADW existe déjà pour cette catégorie.'));

            if ($validator->isValid()) {
                $commentaire = trad::strBuild(('Ajout de la donnée : @1@'), $post['NOM_DATA']);
                ModeleProjetService::updateDoaEvent($this->pdo, $idObjet, $typeObjet, $commentaire);
                
                $this->dataService->createData([
                    'TYPE_OBJET'    => $typeObjet,
                    'ID_OBJET'      => $idObjet,
                    'ID_DONNEE'     => '0',
                    'NUM_ORDRE'     => '0',
                    'NOM_DATA'      => $post['NOM_DATA'],
                    'LIE_A_OBJET'   => ($post['LIE_A_OBJET']??'') === "on",
                    'OBJET'         => $post['OBJET'],
                    'NOM_DATA_ID'   => $post['NOM_DATA_ID'],
                    'TAG_MERGE'     => $post['TAG_MERGE'],
                    'DESCR'         => $post['DESCR'],
                    'MULTIPLE'      => ($post['MULTIPLE']??'') === "on",
                    'ID_CAT'        => $idCategorie,
                    'NOMSQLDW'      => $post['NOMSQLDW'],
                    'CHAMP_NOMSQLDW'=> $post['CHAMP_NOMSQLDW']
                ]);
                
                $this->flash->message($trad->t("La donnée a été créée avec succès"), "success");
                if ("B" === $typeObjet) {
                    return $this->customRedirect('ProjetAchat.BibliothequeDonnee.index', [], ['onglet' => 'data','id' => $idCategorie]);
                } else {
                    return $this->customRedirect(
                        'ProjetAchat.ModeleProjet.details',
                        ['typeObjet' => $typeObjet,'idObjet' => $idObjet],
                        ['onglet' => 'data','id' => $idCategorie]
                    );
                }
            } else {
                return $this->renderer->render('@popup-erreur/ErreurCreation', [
                    'ErreurValid' => $validator->getError(),
                ]);
            }
        }
        
        $bibliothequeRepo = new BibliothequeDonnee($this->pdo);
        $listeObjetTMP = $bibliothequeRepo->getListeObjet(true);
        foreach ($listeObjetTMP as $objet) {
            $listeObjet[$objet['BDD_TABLE']] = $objet['LIBELLE'];
        }

        Ariane::generate(2, $trad->t('Ajout donnée'), $post);

        return $this->renderer->render('@donnee/createedit', [
            'menuActive'            => 'ProjetAchat',
            'action'                => 'create',
            'typeObjet'             => $typeObjet,
            'idObjet'               => $idObjet,
            'category'              => $this->categoryService->findCategory($idCategorie),
            'idCategory'            => $idCategorie,
            'linkedObjects'         => $listeObjet??[],
            'flash'                 => $this->flash
        ]);
    }

    /**
     * @return Response|string
     */
    public function editAction()
    {
        $post = $this->request->getParsedBody();
        $idData = $this->request->getAttribute('idData');
        $donnee = $this->dataService->findFinalData($idData);
        $trad = $this->getTranslationService();

        if ($post) {
            if (isset($post['del_foldersInProgress']) || isset($post['del_TemplatesOnly'])) {
                $commentaire = trad::strBuild(('Modification de la donnée : @1@'), $post['NOM_DATA']);
                ModeleProjetService::updateDoaEvent($this->pdo, $donnee['ID_OBJET'], $donnee['TYPE_OBJET'], $commentaire);

                $post['prePost'] = json_decode($post['prePost'], true);

                if ('false' === $post['del_foldersInProgress'] && 'false' === $post['del_TemplatesOnly']) {
                    $this->dataService->editWithRepercussion('noWhere', $post['prePost'], $idData);
                    $this->flash->message($trad->t("La donnée a été modifiée avec succès"), "success");
                    return new Response(200, [], (string) \json_encode([
                        'statut' => 'O',
                        'path' => $this->router->generateUri('ProjetAchat.BibliothequeDonnee.index', []),
                        'post' => ['onglet' => 'data','id' => $donnee['ID_CAT']],
                    ]));
                } elseif ('true' === $post['del_foldersInProgress']) {
                    $this->dataService->editWithRepercussion('foldersInProgress', $post['prePost'], $idData);
                    $this->flash->message($trad->t("La donnée a été modifiée avec répercussions sur les dossiers en prépation et les modèles avec succès"), "success");
                    return new Response(200, [], (string) \json_encode([
                        'statut' => 'O',
                        'path' => $this->router->generateUri('ProjetAchat.BibliothequeDonnee.index', []),
                        'post' => ['onglet' => 'data','id' => $donnee['ID_CAT']],
                    ]));
                } elseif ('true' === $post['del_TemplatesOnly']) {
                    $this->dataService->editWithRepercussion('templatesOnly', $post['prePost'], $idData);
                    $this->flash->message($trad->t("La donnée a été modifiée avec répercussions sur les modèles avec succès"), "success");
                    return new Response(200, [], (string) \json_encode([
                        'statut' => 'O',
                        'path' => $this->router->generateUri('ProjetAchat.BibliothequeDonnee.index', []),
                        'post' => ['onglet' => 'data','id' => $donnee['ID_CAT']],
                    ]));
                }
            }

            $validator = $this->validateData($post);
            
            if ($post['NOMSQLDW'] && ($donnee['NOMSQLDW']!=$post['NOMSQLDW'])) {
                $validator->isTrue($this->bibliotheque->valeurDataExiste($donnee['TYPE_OBJET'], $donnee['ID_OBJET'], $donnee['ID_CAT'], 'NOMSQLDW', $post['NOMSQLDW']), $trad->t('Le nom de Table OXADW existe déjà pour cette catégorie.'));
            }
            
            $dataUsed = $this->bibliotheque->dataUtilise($idData);

            if ($validator->isValid()) {
                if ($dataUsed) {
                    $trad = $this->getTranslationService();
                    
                    return new Response(200, [
                    ], $this->renderer->render('@popup-erreur/confirmationMultiSuppression', [
                        'message' => $trad->t('Souhaitez-vous que les modifications de la bibliothèque soient répercutées ?'),
                        'div'     => 'redirection',
                        'pathURL' => $this->router->generateUri('ProjetAchat.Donnee.edit', ['idData' => $idData]),
                        'nextPath' => $this->router->generateUri('ProjetAchat.BibliothequeDonnee.index'),
                        'postPath' => "{'onglet' : 'data','id' : '".$donnee['ID_CAT']."'}",
                        'prePost' => json_encode($post)
                    ]));
                } else {
                    $commentaire = trad::strBuild(('Modification de la donnée : @1@'), $post['NOM_DATA']);
                    ModeleProjetService::updateDoaEvent($this->pdo, $donnee['ID_OBJET'], $donnee['TYPE_OBJET'], $commentaire);
                    
                    $this->dataService->editWithRepercussion('noWhere', $post, $idData);
                    
                    if ("B" === $donnee['TYPE_OBJET']) {
                        return new Response(443, [], (string) \json_encode([
                            'statut' => 'O',
                            'path' => $this->router->generateUri('ProjetAchat.BibliothequeDonnee.index', []),
                            'post' => ['onglet' => 'data','id' => $donnee['ID_CAT']],
                        ]));
                    } else {
                        return $this->customRedirect(
                            'ProjetAchat.ModeleProjet.details',
                            ['typeObjet' => $donnee['TYPE_OBJET'],'idObjet' => $donnee['ID_OBJET']],
                            ['onglet' => 'data','id' => $donnee['ID_CAT']]
                        );
                    }
                }
            } else {
                return $this->renderer->render('@popup-erreur/ErreurCreation', [
                    'ErreurValid' => $validator->getError(),
                ]);
            }
        }
        
        $bibliothequeRepo = new BibliothequeDonnee($this->pdo);
        $listeObjetTMP = $bibliothequeRepo->getListeObjet(true);
        foreach ($listeObjetTMP as $objet) {
            $listeObjet[$objet['BDD_TABLE']] = $objet['LIBELLE'];
        }

        Ariane::generate(2, $trad->t('Modification donnée'), $post);
        
        return $this->renderer->render('@donnee/createedit', [
            'menuActive'            => 'ProjetAchat',
            'action'                => 'edit',
            'idData'                => $idData,
            'donnee'                => $donnee,
            'linkedObjects'         => $listeObjet??[],
            'category'              => $this->categoryService->findCategory($donnee['ID_CAT']),
            'idObjet'               => $donnee['ID_OBJET'],
            'typeObjet'             => $donnee['TYPE_OBJET'],
            'flash'                 => $this->flash,
        ]);
    }

    
    public function deleteAction()
    {
        $typeObjet = $this->request->getAttribute('typeObjet');
        $idData =  $this->request->getAttribute('idData');
        $payloadReturn = $this->dataService->getInfosLinkedToData($idData);
        $trad = $this->getTranslationService();
        
        $bibliothequeRepo = new BibliothequeDonnee($this->pdo);
        
        if ($bibliothequeRepo->dataUtilise($idData)) {
            if ($payloadReturn['TYPE_OBJET']=='B') {
                $nextPath = $this->router->generateUri('ProjetAchat.BibliothequeDonnee.index');
            } else {
                $nextPath = $this->router->generateUri('ProjetAchat.ModeleProjet.details', ['typeObjet' => $payloadReturn['TYPE_OBJET'],'idObjet' => $payloadReturn['ID_OBJET']]);
                $postPath = "{'onglet' :  'data', 'id' : '".$payloadReturn['ID_CAT']."' }";
            }
            
            $trad = $this->getTranslationService();
            
            return new Response(443, [
            ], $this->renderer->render('@popup-erreur/confirmationMultiSuppression', [
                'message' => $trad->t('Souhaitez-vous que les modifications de la bibliothèque soient répercutées ?'),
                'div'     => 'redirection',
                'pathURL' => $this->router->generateUri('ProjetAchat.Donnee.deleteHeritage', ['typeObjet' => $payloadReturn['TYPE_OBJET'],'idData' => $idData]),
                'form'    => '',
                'nextPath' => $nextPath,
                'postPath' => $postPath??'',
            ]));
        } else {
            $commentaire = trad::strBuild(('Suppression de la donnée : @1@'), $payloadReturn['NOM_DONNEE']);
            ModeleProjetService::updateDoaEvent($this->pdo, $payloadReturn['ID_OBJET'], $typeObjet, $commentaire);

            $this->dataService->supprimerDonnee($typeObjet, 0, $idData, 2);
            
            return new Response(200, [
                
            ], (string) \json_encode([
                'path' => $this->router->generateUri('ProjetAchat.BibliothequeDonnee.ajaxDetailCategorie', ['idCategorie' => $payloadReturn['ID_CAT'], 'idObjet' => $payloadReturn['ID_OBJET'], 'typeObjet' => $payloadReturn['TYPE_OBJET']]),
            ]));
        }
    }
    
    /**
     * @return Response
     *
     * Ajax call
     */
    public function deleteHeritageAction()
    {
        $post = $this->request->getParsedBody();
        $idData =  $this->request->getAttribute('idData');
        $typeObjet = $this->request->getAttribute('typeObjet');
        $payloadReturn = $this->dataService->getInfosLinkedToData($idData);
        $trad = $this->getTranslationService();

        if ('false' === $post['del_foldersInProgress'] && 'false' === $post['del_TemplatesOnly']) {
            $this->dataService->supprimerDonnee($typeObjet, 0, $idData, 2);
        } elseif ('true' === $post['del_foldersInProgress']) {
            $this->dataService->supprimerDonnee($typeObjet, 0, $idData, 0);
        } elseif ('true' === $post['del_TemplatesOnly']) {
            $this->dataService->supprimerDonnee($typeObjet, 0, $idData, 1);
        }
        
        $commentaire = trad::strBuild(('Suppression de la donnée : @1@'), $payloadReturn['NOM_DATA']);
        ModeleProjetService::updateDoaEvent($this->pdo, $payloadReturn['ID_OBJET'], $typeObjet, $commentaire);

        return new Response(200, [

        ], (string) \json_encode([
            'path' => $this->router->generateUri('ProjetAchat.BibliothequeDonnee.ajaxDetailCategorie', ['idCategorie' => $payloadReturn['ID_CAT'], 'idObjet' => $payloadReturn['ID_OBJET'], 'typeObjet' => $payloadReturn['TYPE_OBJET']]),
        ]));
    }
    
    
    public function briserHeritageAction()
    {
        $typeObjet = $this->request->getAttribute('typeObjet');
        $idObjet = $this->request->getAttribute('idObjet');
        $idData =  $this->request->getAttribute('idData');
        
        $payloadReturn = $this->dataService->getInfosLinkedToData($idData);
        
        $this->dataService->briserHeritage($typeObjet, $idObjet, $idData);
        
        return new Response(200, [
            
        ], (string) \json_encode([
            'path' => $this->router->generateUri('ProjetAchat.BibliothequeDonnee.ajaxDetailCategorie', ['idCategorie' => $payloadReturn['ID_CAT'], 'idObjet' => $idObjet, 'typeObjet' => $typeObjet]),
        ]));
    }

    /**
     * @param string $path
     * @return Response
     */
    private function customRedirect(string $path, array $params = [], $post = [])
    {
        return new Response(443, [], (string) \json_encode([
            'statut' => 'O',
            'path' => $this->router->generateUri($path, $params),
            'post' => $post,
        ]));
    }

     /**
     * @param array<string> $payload
     * @return \Helpers\Validator\Validator
    */
    private function validateData(array $payload)
    {
        $trad = $this->getTranslationService();
        
        $validator = $this->createValidator();
        
        $validator->isStringAvecEspace($trad->t('Nom'), $payload['NOM_DATA'], 1, 120);
        $validator->isStringAvecEspace($trad->t('Description'), $payload['DESCR'], 0, 3000);
        $validator->isFalse(preg_match('/^[a-zA-Z0-9_]*$/', $payload['NOMSQLDW']), Trad::strBuild($trad->t('Le champ @1@ ne peut contenir que les caractères suivants 0-9, A-Z, et « _ ».'), $trad->t('Table OXADW')));
        $validator->isCheck($payload['MULTIPLE']);
        
        if (($payload['LIE_A_OBJET']??'') === "on") {
            $validator->isFalse($payload['OBJET'], Trad::strBuild($trad->t('Le champ @1@ ne peut pas être vide.'), $trad->t('Objet lié')));

            $validator->isTrue((($payload['OBJET'] == 'AO_ENTET') && $payload['MULTIPLE']), $trad->t('La donnée consultation ne peut pas être multiple.'));
        }
        
        return $validator;
    }
}
