<?php

namespace Modules\ProjetAchat\Controller;

use GuzzleHttp\Psr7\Response;
use Helpers\Ariane\Ariane;
use Helpers\Trad\Trad;
use Modules\ProjetAchat\Service\HierarchyService;
use Modules\ProjetAchat\Service\TaskService;
use Psr\Container\ContainerInterface;
use Skeleton\Controller\Controller;
use Skeleton\Renderer\RendererInterface;
use Skeleton\Router;
use Tamtamchik\SimpleFlash\Flash;
use Entity\Model\DoaTaches;
use Helpers\Outil\Date;
use Modules\ProjetAchat\Service\ModeleProjetService;
use Helpers\Outil\Sql;

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

    /**
     * @var HierarchyService $hierarchyService
     */
    private $hierarchyService;

    /**
     * @var TaskService $taskService
     */
    private $taskService;

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

    /**
     * @return Response|string
     */
    public function createAction()
    {
        $typeObjet = $this->request->getAttribute('typeObjet');
        $idObjet = $this->request->getAttribute('idObjet');
        $idHierarchy = $this->request->getAttribute('idHierarchy');
        $unavailableDays = $this->taskService->getUnavailablesDays($idObjet);
        $trad = $this->getTranslationService();

        $post = $this->request->getParsedBody();

        if ($post) {
            if (($post['DATE_DEB']??null) && ($post['DATE_FIN']??null) && 0 == $post['submitForce']) {
                $dateDeb = $post['DATE_DEB'];
                date::dateToSql($dateDeb);
                $dateDeb = Date::dateConverte($dateDeb, 'aaaa-mm-jj');
                
                $dateFin = $post['DATE_FIN'];
                date::dateToSql($dateFin);
                $dateFin = Date::dateConverte($dateFin, 'aaaa-mm-jj');
                $dateStart = new \Moment\Moment($dateDeb);
                $dateEnd = new \Moment\Moment($dateFin);
                
                if (in_array($dateStart->format('j-n-Y'), $unavailableDays) || in_array($dateEnd->format('j-n-Y'), $unavailableDays)) {
                    $params = [
                        'avertissement' => $trad->t('Vous avez sélectionné une date définie comme fermée dans votre paramétrage'),
                        'action' => 'saveTask',
                        'titrePopup'  => $trad->t('Avertissement'),
                    ];
                    return new Response(200, [
                    ], $this->renderer->render('@popup-erreur/erreurAlerteEtAvertissement', ['params' => $params]));
                }
            }

            $validator = $this->validateTask($post, $typeObjet);

            if ($validator->isValid()) {
                $commentaire = Trad::strBuild(('Ajout de la tâche : @1@'), $post['LIB']);
                ModeleProjetService::updateDoaEvent($this->pdo, $idObjet, $typeObjet, $commentaire);
                
                $this->taskService->createTask([
                    'TYPE_OBJET'    => $typeObjet,
                    'ID_OBJET'      => $idObjet,
                    'ID_TACHE_H'    => $post['ID_TACHE_H'],
                    'LIB'           => $post['LIB'],
                    'DESCR'         => $post['DESCR'],
                    'RESPONSABLE'   => $post['RESPONSABLE'],
                    'DATE_DEB'      => $post['DATE_DEB'] ?? 0,
                    'DATE_FIN'      => $post['DATE_FIN'] ?? 0,
                    'TERMINEE'      => false,
                    'DUREE_PREV'    => $post['DUREE_PREV'],
                    'SOUMISE_ALERTE'=> ($post['SOUMISE_ALERTE']??'') === "on",
                    'DELAI_PREAVIS' => $post['DELAI_PREAVIS'],
                    'TYPE_ALERTE'   => ($post['SOUMISE_ALERTE']??'') === "on" ? $post['TYPE_ALERTE'] : '',
                    'ID_PROC'       => $post['ID_PROC']??'',
                    'CHAP_PROC'     => $post['CHAP_PROC']??'',
                    'ID_ETAT_AV'    => $post['ID_ETAT_AV'],
                    'NUM_ORDRE'     => $this->taskService->getRightOrder($post['ID_TACHE_H'], $typeObjet)
                ]);
                
                $this->flash->message($trad->t("La tâche a été créée avec succès"), "success");
                
                return $this->customRedirect('ProjetAchat.ModeleProjet.details', [
                    'typeObjet' => $typeObjet,
                    'idObjet' => $this->request->getAttribute('idObjet')
                ], ['onglet' => 'tasks','id' => $post['ID_TACHE_H']]);
            } else {
                return $this->renderer->render('@popup-erreur/ErreurCreation', [
                    'ErreurValid' => $validator->getError(),
                ]);
            }
        } else {
            if ($typeObjet === 'D') {
                $post['DATE_DEB'] = $this->taskService->getNonBusyDate($idHierarchy, $idObjet);
            }
            $post['DELAI_PREAVIS'] = Sql::paravrac($this->pdo, 'PARAMGEN', 'DOA_DELAI_ALERTE');
        }

        Ariane::generate(2, 'Add task', $post);

        $listeDeclencheur = [
            'P' => $trad->t('Propriétaire du Projet'),
            'S' => $trad->t('Prescripteur du Projet'),
            ''  => $trad->t('A définir dans le projet')
        ];

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

        $trad = $this->getTranslationService();
        if ($listeTypeActeur) {
            foreach ($listeTypeActeur as $key => $acteur) {
                $numFix = explode('|', $key);
                $listeDeclencheur['CS_'.$numFix[1]] = $trad->t($acteur);
            }
        }

        return $this->renderer->render('@task/createedit', [
            'menuActive'            => 'ProjetAchat',
            'action'                => 'create',
            'startDate'             => $typeObjet === 'D' ? $this->taskService->getNonBusyDate($idHierarchy, $idObjet) : '',
            'unavailableDays'       => json_encode($unavailableDays),
            'typeObjet'             => $typeObjet,
            'idObjet'               => $idObjet,
            'hierarchy'             => $this->hierarchyService->findHierarchy($idHierarchy),
            'idHierarchy'           => $idHierarchy,
            'procedures'            => $this->taskService->getProcedures(),
            'progressStates'        => $this->taskService->getProgressStates(),
            'flash'                 => $this->flash,
            'task'                  => $post,
            'listeDeclencheur'      => $listeDeclencheur,
        ]);
    }

    /**
     * @return Response|string
     */
    public function editAction()
    {
        $post = $this->request->getParsedBody();
        $idTask = $this->request->getAttribute('idTask');
        $task = $this->taskService->findTask($idTask);
        $typeObjet = $this->taskService->getTypeObject($task['ID_OBJET']);
        $unavailableDays = $this->taskService->getUnavailablesDays($task['ID_OBJET']);
        $trad = $this->getTranslationService();
        
        $doaTachesEntity = new DoaTaches($this->pdo);
        $doaTache = $doaTachesEntity->find($idTask);
        
        if ($post) {
            if (isset($post['DATE_DEB']) && ($post['DATE_DEB'] && $post['DATE_DEB'] != '00000000') && ($post['DATE_FIN'] && $post['DATE_FIN']!= '00000000') && 0 == $post['submitForce']) {
                $dateDeb = $post['DATE_DEB'];
                date::dateToSql($dateDeb);
                $dateDeb = Date::dateConverte($dateDeb, 'aaaa-mm-jj');
                
                $dateFin = $post['DATE_FIN'];
                date::dateToSql($dateFin);
                $dateFin = Date::dateConverte($dateFin, 'aaaa-mm-jj');
                $dateStart = new \Moment\Moment($dateDeb);
                $dateEnd = new \Moment\Moment($dateFin);
                
                if (in_array($dateStart->format('j-n-Y'), $unavailableDays) || in_array($dateEnd->format('j-n-Y'), $unavailableDays)) {
                    $params = [
                        'avertissement' => $trad->t('Vous avez sélectionné une date définie comme fermée dans votre paramétrage'),
                        'action' => 'saveTask',
                        'titrePopup'  => $trad->t('Avertissement'),
                    ];
                    return new Response(200, [
                    ], $this->renderer->render('@popup-erreur/erreurAlerteEtAvertissement', ['params' => $params]));
                }
            }

            $validator = $this->validateTask($post, $typeObjet);

            if ($validator->isValid()) {
                if ($post['RESPONSABLE'] != $doaTache['RESPONSABLE']) {
                    $taskRepo = new \Modules\ProjetAchat\Repository\Task($this->pdo);
                    $taskRepo->updateRaciByResponsable($typeObjet, $task['ID_OBJET'], $idTask, $post['RESPONSABLE']);
                }
                
                date::dateToSql($post['DATE_DEB']);
                date::dateToSql($post['DATE_FIN']);
                
                $commentaire = trad::strBuild(('Modification de la tâche : @1@'), $post['LIB']);
                ModeleProjetService::updateDoaEvent($this->pdo, $task['ID_OBJET'], $typeObjet, $commentaire);
                
                $this->taskService->editTask([
                    'LIB'           => $post['LIB'],
                    'DESCR'         => $post['DESCR'],
                    'RESPONSABLE'   => $post['RESPONSABLE'],
                    'DUREE_PREV'    => $post['DUREE_PREV'],
                    'SOUMISE_ALERTE'=> ($post['SOUMISE_ALERTE']??'') === "on",
                    'DELAI_PREAVIS' => $post['DELAI_PREAVIS'],
                    'TYPE_ALERTE'   => $post['TYPE_ALERTE'],
                    'ID_PROC'       => $post['ID_PROC']??'',
                    'CHAP_PROC'     => $post['CHAP_PROC']??'',
                    'ID_ETAT_AV'    => $post['ID_ETAT_AV'],
                    'DATE_DEB'      => $post['DATE_DEB'],
                    'DATE_FIN'      => $post['DATE_FIN'],
                ], $idTask);
                
                $this->flash->message($trad->t("La tâche a été modifiée avec succès"), "success");
                
                return $this->customRedirect('ProjetAchat.ModeleProjet.details', [
                    'typeObjet' => $typeObjet,
                    'idObjet' => $task['ID_OBJET']
                ], ['onglet' => 'tasks','id' => $task['ID_TACHE_H']]);
            } else {
                return $this->renderer->render('@popup-erreur/ErreurCreation', [
                    'ErreurValid' => $validator->getError(),
                ]);
            }
        }


        $listeDeclencheur = [
            'P' => $trad->t('Propriétaire du Projet'),
            'S' => $trad->t('Prescripteur du Projet'),
            ''  => $trad->t('A définir dans le projet')
        ];

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

        if ($listeTypeActeur) {
            foreach ($listeTypeActeur as $key => $acteur) {
                $numFix = explode('|', $key);
                $listeDeclencheur['CS_'.$numFix[1]] = $trad->t($acteur);
            }
        }
        
        return $this->renderer->render('@task/createedit', [
            'menuActive'            => 'ProjetAchat',
            'action'                => 'edit',
            'idTask'                => $idTask,
            'unavailableDays'       => json_encode($this->taskService->getUnavailablesDays($task['ID_OBJET'])),
            'task'                  => $task,
            'flash'                 => $this->flash,
            'procedures'            => $this->taskService->getProcedures(),
            'progressStates'        => $this->taskService->getProgressStates(),
            'typeObjet'             => $typeObjet,
            'idObjet'               => $task['ID_OBJET'],
            'idHierarchy'           => $doaTache['ID_TACHE_H'],
            'listeDeclencheur'      => $listeDeclencheur,
        ]);
    }

    public function detailsAction() : string
    {
        $trad = $this->getTranslationService();
        $listeDeclencheur = [
            'P' => $trad->t('Propriétaire du Projet'),
            'S' => $trad->t('Prescripteur du Projet'),
            ''  => $trad->t('A définir dans le projet')
        ];

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

        if ($listeTypeActeur) {
            foreach ($listeTypeActeur as $key => $acteur) {
                $numFix = explode('|', $key);
                $listeDeclencheur['CS_'.$numFix[1]] = $trad->t($acteur);
            }
        }

        return $this->renderer->render('@task/details', [
            'menuActive'            => 'ProjetAchat',
            'task'                  => $this->taskService->getTask($this->request->getAttribute('idTask')),
            'listeDeclencheur'      => $listeDeclencheur,
        ]);
    }

    /**
     * @return string
     *
     * Ajax call
     */
    public function findEndDateAction() : string
    {
        $post = $this->request->getParsedBody();

        return $this->taskService->getNonBusyDate(
            $post['idHierarchy'],
            $post['idProject'],
            $post['startDate'],
            $post['durationPrev'],
        );
    }

    /**
     * @return Response
     *
     * Ajax call
     */
    public function deleteAction()
    {
        $idTask =  $this->request->getAttribute('idTask');
        $task = $this->taskService->findTask($idTask);
        $typeObjet = $this->taskService->getTypeObject($task['ID_OBJET']);
        $trad = $this->getTranslationService();

        $commentaire = trad::strBuild(('Suppression de la tâche : @1@'), $task['LIB']);
        ModeleProjetService::updateDoaEvent($this->pdo, $task['ID_OBJET'], $typeObjet, $commentaire);
        
        $this->taskService->deleteTask($idTask);
        
        return new Response(200, [], (string) \json_encode([
            'path' => $this->router->generateUri('ProjetAchat.Hierarchy.ajaxDetailHierarchy', [
                'typeObjet' => $typeObjet,
                'idObjet' => $task['ID_OBJET'],
                'idCategorie' => $task['ID_TACHE_H'],
            ]),
        ]));
    }

    public function ajaxReorderTaskAction() : string
    {
        $post = $this->request->getParsedBody();
        
        if ($post['initialPosition'] > $post['newPosition']) {
            $post['sign'] = "+";
        } else {
            $post['sign'] = "-";
        }
        
        $taskRepo = new \Modules\ProjetAchat\Repository\Task($this->pdo);
        $taskRepo->reorderTask($post);

        return "true";
    }
    
    /**
     * @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
     * @return \Helpers\Validator\Validator
     */
    private function validateTask(array $payload, string $typeObject = "")
    {
        $trad = $this->getTranslationService();
        
        $validator = $this->createValidator();
        $validator->isStringAvecEspace($trad->t('Libellé'), $payload['LIB'], 1, 120);
        
        $validator->isInteger($trad->t('Durée prévisionnelle'), $payload['DUREE_PREV'], 1, 3);
        $validator->isTrue(($payload['DUREE_PREV']=='0'), $trad->t('La durée prévisionnelle doit être supérieure à 0.'));
        
        if ("D" === $typeObject) {
            $validator->isStringAvecEspace('Responsable', $payload['RESPONSABLE'], 1, 100);
            $validator->isDate($payload['DATE_DEB'], '', '', false, $trad->t('date de début'));
            $validator->isDate($payload['DATE_FIN'], '', '', false, $trad->t('date de fin'));
            
            $validator->isCoherenceDate($payload['DATE_DEB'], $payload['DATE_FIN']);
        }
        return $validator;
    }
}
