<?php

namespace Modules\ProjetAchat\Controller;

use Helpers\Outil\Sql;
use Helpers\Validator\Validator;
use Modules\ProjetAchat\Service\HierarchyService;
use Psr\Container\ContainerInterface;
use Skeleton\Controller\Controller;
use Helpers\Ariane\Ariane;
use Helpers\Trad\Trad;
use Skeleton\Renderer\RendererInterface;
use Skeleton\Router;
use \Tamtamchik\SimpleFlash\Flash;
use GuzzleHttp\Psr7\Response;
use Entity\Model\Doa;
use Modules\ProjetAchat\Repository\Task;
use Helpers\Outil\Roles;
use Modules\ProjetAchat\Service\ModeleProjetService;
use Entity\Model\DoaTacheH;
use Modules\ProjetAchat\Repository\Action;
use Entity\Model\DoaAction;
use Modules\ProjetAchat\MenuContextuel\DetailHierarchyMenuContextuel;

class HierarchyController extends Controller
{
    /**
     * @var HierarchyService $hierarchyService
     */
    private $hierarchyService;

    /**
     * @var Flash $flash
     */
    private $flash;

    /**
     * CategorieController 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->hierarchyService = new HierarchyService($this->pdo);
        $this->flash = new Flash();
    }

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

        if ($post) {
            $validator = $this->validateHierarchy($post);
            if ($validator->isValid()) {
                $commentaire = trad::strBuild($trad->t('Ajout de la catégorie de tâche @1@'), $post['LIB']);
                ModeleProjetService::updateDoaEvent($this->pdo, $idObjet, $typeObjet, $commentaire);
                
                $this->hierarchyService->createHierarchy([
                    'TYPE_OBJET'    => $typeObjet,
                    'ID_OBJET'      => $idObjet,
                    'ID_PARENT'     => $post['ID_PARENT'],
                    'LIB'           => $post['LIB'],
                    'DESCR'         => $post['DESCR'],
                    'NUM_ORDRE'     => $this->hierarchyService->getRightOrder((int) $post['ID_PARENT'], $typeObjet, $idObjet)
                ]);
                
                $this->flash->message($trad->t("La catégorie de tâche a été créée avec succès"), "success");

                return $this->customRedirect('ProjetAchat.ModeleProjet.details', [
                    'typeObjet' => $typeObjet,
                    'idObjet' => $idObjet
                ], ['onglet' => 'tasks','id' => '99999']);
            } else {
                return $this->renderer->render('@popup-erreur/ErreurCreation', [
                    'ErreurValid' => $validator->getError(),
                ]);
            }
        }

        Ariane::generate(2, $trad->t('Ajout catégorie de tâche'), $post);
        
        $cancelPath = $this->router->generateUri('ProjetAchat.ModeleProjet.details', [
            'typeObjet' => $typeObjet,
            'idObjet' => $idObjet
        ]);
        
        return $this->renderer->render('@projetAchat/ProjetAchat/tabs/add_hierarchy', [
            'menuActive'            => 'ProjetAchat',
            'action'                => 'create',
            'category'              =>  $idParent? $this->hierarchyService->findHierarchy($idParent) : [],
            'idCategory'            => null,
            'flash'                 => $this->flash,
            'typeObject'            => $typeObjet,
            'idObject'              => $idObjet,
            'idParent'              => $idParent,
            'isParent'              => $isParent,
            'cancelPath'            => $cancelPath,
            'refCategory'           => ['ref'   => $idParent ? $this->hierarchyService->findHierarchy($idParent) : [],'type'  => (int) $isParent === 1 ? 'parent' : 'sister'],
        ]);
    }

    /**
     * @return Response|string
     */
    public function editAction()
    {
        $post = $this->request->getParsedBody();
        $idHierarchy = $this->request->getAttribute('idHierarchy');
        $hierarchy = $this->hierarchyService->findHierarchy($idHierarchy);
        $typeObjet = $hierarchy['TYPE_OBJET'];
        $trad = $this->getTranslationService();

        if ($post) {
            $validator = $this->validateHierarchy($post);
            if ($validator->isValid()) {
                $commentaire = trad::strBuild($trad->t('Modification de la catégorie de tâche @1@'), $post['LIB']);
                ModeleProjetService::updateDoaEvent($this->pdo, $hierarchy['ID_OBJET'], $typeObjet, $commentaire);
                
                $this->hierarchyService->updateHierarchy([
                    'LIB'           => $post['LIB'],
                    'DESCR'         => $post['DESCR'],
                ], $idHierarchy);
                
                $this->flash->message($trad->t("La catégorie de tâche a été modifiée avec succès"), "success");
                
                return $this->customRedirect('ProjetAchat.ModeleProjet.details', [
                    'typeObjet' => $hierarchy['TYPE_OBJET'],
                    'idObjet' => $hierarchy['ID_OBJET']
                ], ['onglet' => 'tasks','id' => '99999']);
            } else {
                return $this->renderer->render('@popup-erreur/ErreurCreation', [
                    'ErreurValid' => $validator->getError(),
                ]);
            }
        }

        Ariane::generate(2, $trad->t('Modifier une catégorie de tâche'), $post);

        $cancelPath = $this->router->generateUri('ProjetAchat.ModeleProjet.details', [
            'typeObjet' => $hierarchy['TYPE_OBJET'],
            'idObjet' => $hierarchy['ID_OBJET']
        ]);

        return $this->renderer->render('@projetAchat/ProjetAchat/tabs/add_hierarchy', [
            'menuActive'            => 'ProjetAchat',
            'action'                => 'edit',
            'hierarchy'             => $hierarchy,
            'idHierarchy'           => $idHierarchy,
            'flash'                 => $this->flash,
            'cancelPath'            => $cancelPath,
        ]);
    }

    public function deleteAction() : string
    {
        $idHierarchy = $this->request->getAttribute('idHierarchy');
        
        $hierarchyEntity = new DoaTacheH($this->pdo);
        $hierarchy = $hierarchyEntity->find($idHierarchy);
        
        $this->hierarchyService->deleteHierarchy($idHierarchy);
        $trad = $this->getTranslationService();
          
        $commentaire = trad::strBuild($trad->t('Suppression de la catégorie de tâche @1@'), $hierarchy['LIB']);
        ModeleProjetService::updateDoaEvent($this->pdo, $hierarchy['ID_OBJET'], $hierarchy['TYPE_OBJET'], $commentaire);
        
        $this->flash->message($trad->t('La catégorie de tâche a été supprimée avec succès'), "success");

        return '';
    }

    public function ajaxDetailHierarchyAction() : string
    {
        $idCategorie = $this->request->getAttribute('idCategorie');
        $typeObjet = $this->request->getAttribute('typeObjet');
        $idObjet = $this->request->getAttribute('idObjet');
        
        $categorieAFille = $this->hierarchyService->hasChilds($typeObjet, $idObjet, $idCategorie);
        $infoHierarchy = $this->hierarchyService->findHierarchy($idCategorie);
        $tasks = $this->hierarchyService->getTaskCurrentHierarchy($idCategorie);
        $this->hierarchyService->errorOrderHierarchy($typeObjet, $idObjet, $idCategorie, $tasks);

        $droit = [
            'DOA_DOA_CM' => Roles::droitsUtilisateur($this->pdo, 'DOA_DOA_CM', $_SESSION["Session_Login"]),
            'DOA_DOA_TT' => Roles::droitsUtilisateur($this->pdo, 'DOA_DOA_TT', $_SESSION["Session_Login"]),
            'DOA_MOD_CM' => Roles::droitsUtilisateur($this->pdo, 'DOA_MOD_CM', $_SESSION["Session_Login"]),
            'DOA_MOD_TT' => Roles::droitsUtilisateur($this->pdo, 'DOA_MOD_TT', $_SESSION["Session_Login"]),
        ];

        $doaEntity = new Doa($this->pdo);
        $infoDOA = $doaEntity->find($idObjet);
        
        // TODO : factorize
        $canEdit =
            $typeObjet == 'B'
            || (
                $typeObjet == 'M'
                && (
                    ($droit['DOA_MOD_CM'] && $infoDOA['PROPRIETAIRE'] == $_SESSION["Session_Login"])
                    || $droit['DOA_MOD_TT']
                )
            ) || (
                $typeObjet == 'D'
                && ! Sql::toBool($infoDOA['SUSPENDU'] ?? false)
                && (
                    ($infoDOA['STATUT']??'')=='I'
                    || ($infoDOA['STATUT']??'') == 'P'
                )
            ) && (
                ($droit['DOA_DOA_CM'] && $infoDOA['PROPRIETAIRE'] == $_SESSION["Session_Login"])
                || $droit['DOA_DOA_TT']
            );
        
        $tasksRepo = new Task($this->pdo);
        
        $actionRepo = new Action($this->pdo);
        $doaActionEntity = new DoaAction($this->pdo);

        $menuContextuel = new DetailHierarchyMenuContextuel($this->pdo, $this->router, $this->getTranslationService());
        foreach ($tasks as &$val) {
            $actions = $tasksRepo->getListAction($val['ID_TACHE']);
            if ($canEdit) {
                $val['menuContextuel'] = $menuContextuel->generateTask($typeObjet, $idObjet, $val);
            }
            
            if ($actionRepo->getErrorOrderAction($typeObjet, $idObjet, $val['ID_TACHE'])) {
                $i = 1;
                foreach ($actions as &$orderAction) {
                    $doaActionEntity->update(['NUM_ORDRE' => $i], $orderAction['ID_ACTION']);
                    $orderAction['NUM_ORDRE'] = $i;
                    $i++;
                }
            }
            
            if ($infoDOA['STATUT'] == 'E') {
                foreach ($actions as &$action) {
                    $action['isExecutable'] = (
                        $tasksRepo->isExecutable($action['ID_ACTION'], $_SESSION['Session_Login'])
                        || $infoDOA['PROPRIETAIRE'] == $_SESSION['Session_Login']
                    ) && $infoDOA['STATUT'] == 'E' && ! Sql::toBool($infoDOA['SUSPENDU']);
                }
            }
            foreach ($actions as &$action) {
                if ($canEdit) {
                    $action['menuContextuel'] = $menuContextuel->generateAction($typeObjet, $idObjet, $val, $action);
                }
            }
            $val['listAction'] = $actions;
        }

        $trad = $this->getTranslationService();

        $modeleProjetService = new ModeleProjetService($this->pdo);
        $listeTypeActeur = $modeleProjetService->generateListTypeActeur('DOA', $trad);
        

        $userCS = [];
        if ($listeTypeActeur) {
            foreach ($listeTypeActeur as $key => $acteur) {
                $numFix = explode('|', $key);
                $userCS['CS_'.$numFix[1]] = $trad->t($acteur);
            }
        }
        
        return $this->renderer->render('@projetAchat/ProjetAchat/ajaxDetailHierarchy', [
            'infoHierarchy' => $infoHierarchy,
            'tasks' => $tasks,
            'categorieAFille' => $categorieAFille,
            
            'idHierarchy' => $idCategorie,
            'typeObjet' => $typeObjet,
            'idObjet' => $idObjet,
            'flash'  => $this->flash,
            'droit' => $droit,
            'statut' => $infoDOA['STATUT']??'',
            'userCS' => $userCS,
            'canEdit'  => $canEdit
        ]);
    }
    
    public function ajaxMenuContextuelHAction() : string
    {
        $idHierarchy = $this->request->getAttribute('idHierarchy');
        $hierarchy = $this->hierarchyService->findHierarchy($idHierarchy);
        
        return $this->renderer->render('@projetAchat/ProjetAchat/ajaxMenuContextuelH', [
            'idHierarchy'    => $this->request->getAttribute('idHierarchy'),
            'hierarchy'      => $hierarchy,
            'hierarchyJson'  => json_encode($hierarchy),
            'idParent'       => $this->hierarchyService->getParentHierarchy($idHierarchy),
            'typeObject'    => $hierarchy['TYPE_OBJET'],
            'idObject'      => $hierarchy['ID_OBJET'],
        ]);
    }
    
    public function ajaxReOrderAction()
    {
        $typeObjet = $this->request->getAttribute('typeObject');
        $idObjet = $this->request->getAttribute('idObject');
        $post = $this->request->getParsedBody();
        
        $post['oldParent'] = $post['oldParent']=='#'? '0':$post['oldParent'];
        $post['parent'] = $post['parent']=='#'? '0':$post['parent'];
        
        $this->hierarchyService->reOrder($typeObjet, $idObjet, $post['idHierarchy'], $post['oldParent'], $post['parent'], $post['old_position'], $post['position']);
        
        return new Response(200);
    }

    /**
     * @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<mixed> $payload
     */
    private function validateHierarchy(array $payload) :Validator
    {
        $validator = $this->createValidator();
        $validator->isStringAvecEspace('Catégorie', $payload['LIB'], 1, 120);
        return $validator;
    }
}
