<?php 
 
namespace App\Controller\Athena; 
 
use App\Entity\Athena\Page; 
use App\Entity\Athena\User; 
use App\Entity\Athena\VideoTutorial; 
use App\Form\Athena\DeleteForm; 
use App\Service\Asclepios\ClinicService; 
use App\Service\Athena\ComingSoonLogoutService; 
use App\Service\Athena\ContextService; 
use App\Service\Athena\DatatableService; 
use App\Service\Athena\PageService; 
use App\Service\Athena\TranslationService; 
use App\Service\Hephaistos\DateService; 
use Doctrine\Persistence\ObjectRepository; 
use Exception; 
use ReflectionClass; 
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; 
use Symfony\Component\HttpFoundation\Cookie; 
use Symfony\Component\HttpFoundation\HeaderUtils; 
use Symfony\Component\HttpFoundation\JsonResponse; 
use Symfony\Component\HttpFoundation\Request; 
use Symfony\Component\HttpFoundation\RequestStack; 
use Symfony\Component\HttpFoundation\Response; 
use Symfony\Component\HttpKernel\Profiler\Profiler; 
use Symfony\Component\Routing\Annotation\Route; 
use Symfony\Component\Security\Core\Security; 
use Symfony\Contracts\Translation\TranslatorInterface; 
 
class DefaultController extends AbstractController 
{ 
    const DEFAULT_TEMPLATE = 'Athena/index'; 
    const TEMPLATE_EXTENSION = '.html.twig'; 
 
    const STATUS_MESSAGE = 'message'; 
    const STATUS_WARNING = 'warning'; 
    const STATUS_ERROR = 'error'; 
    const STATUS_EXCEPTION = 'exception'; 
    const TAG_BREADCRUMB = 'a-breadcrumb'; 
    const TAG_BUTTONS = 'a-buttons'; 
    const TAG_JAVASCRIPT = 'a-javascript'; 
    const TAG_KEEP_MODAL_OPENED = 'a-keep-modal-opened'; 
 
    const TAG_MAIN = 'a-main'; 
    const TAG_MAIN_OVERTITLE = 'a-main-overtitle'; 
    const TAG_MAIN_SUBTITLE = 'a-main-subtitle'; 
    const TAG_MAIN_TITLE = 'a-main-title'; 
    const TAG_MODAL_TITLE = 'a-modal-title'; 
    const TAG_MODAL_CONTENT = 'a-modal-content'; 
    const TAG_MODAL_CLOSABLE = 'a-modal-closable'; 
    const TAG_ERROR_TITLE = 'a-error-title'; 
    const TAG_ERROR_CONTENT = 'a-error-content'; 
    const TAG_PREVENT_URL_UPDATE = 'a-prevent-url-update'; 
    const TAG_REDIRECT = 'a-redirect'; 
    const TAG_REDIRECT_WITHOUT_LOADER = 'a-redirect-without-loader'; 
    const TAG_REDRAW_BRICK_ID = 'a-redraw-brick-id'; 
    const TAG_REDRAW_BRICK_DATAS = 'a-redraw-brick-datas'; 
    const TAG_RELOAD_IFRAME = 'a-reload-iframe'; 
    const TAG_SET_VALUE = 'a-set-value'; 
    const TAG_STATUS = 'a-status'; 
    const TAG_TARGET_BLANK = 'a-target-blank'; 
    const TAG_FORM_BLANK = 'a-form-blank'; 
    const TAG_FORM_BLANK_DATAS = 'a-form-blank-datas'; 
    const TAG_FUNCTION_ON_LOAD = 'a-function-on-load'; 
    const TAG_SCROLL_TO_TOP = 'a-scroll-content-to-top'; 
 
    const TAG_KEEP_SIDEBAR_MODAL_OPENED = 'a-keep-sidebar-modal-opened'; 
 
    const TAG_SIDEBAR_MODAL_TITLE = 'a-sidebar-modal-title'; 
 
    const TAG_SIDEBAR_MODAL_CONTENT = 'a-sidebar-modal-content'; 
    const TAG_HIDE_MAIN_TITLE = 'a-hide-main-title'; 
    const TAG_SIDEBAR_MODAL_ICON = 'a-sidebar-modal-icon'; 
    const TAG_ONBOARDING = 'a-onboarding'; 
    const TAG_SET_INNER_HTML = 'a-set-inner-html'; 
    const TAG_VIDEO_TUTORIAL = 'a-video-tutorial'; 
 
    protected array $args; 
    protected array $cookies; 
    protected ClinicService $clinicService; 
    protected ContextService $context; 
    protected DateService $dateService; 
    protected DatatableService $datatableService; 
    protected string $domain; 
    protected string $entityClass; 
    protected string $entityName; 
    protected string $file; 
    protected string $fileDisposition = HeaderUtils::DISPOSITION_ATTACHMENT; 
    protected string $fileName; 
    protected bool $isJson; 
    protected array $otherData; 
    protected array $extractData; 
    protected PageService $pageService; 
    protected ?Request $request; 
    protected string $routePrefix; 
    protected ?Security $security; 
    protected string $template; 
    protected TranslationService $translationService; 
    protected TranslatorInterface $translator; 
    private ComingSoonLogoutService $comingSoonLogoutService; 
 
    private static array $messagesFromService; 
 
    private bool $newDesign = false; 
 
    public function __construct( 
        ClinicService           $clinicService, 
        DatatableService        $datatableService, 
        DateService             $dateService, 
        PageService             $pageService, 
        RequestStack            $requestStack, 
        Security                $security, 
        TranslationService      $translationService, 
        TranslatorInterface     $translator, 
        ContextService          $context, 
        ComingSoonLogoutService $comingSoonLogoutService 
    ) 
    { 
        $this->comingSoonLogoutService = $comingSoonLogoutService; 
        if ($this->comingSoonLogoutService->isComingSoon()) { 
            $this->comingSoonLogoutService->logoutAllConnectedUser(); 
        } 
        $this->args = []; 
        $this->cookies = []; 
        $this->clinicService = $clinicService; 
        $this->dateService = $dateService; 
        $this->datatableService = $datatableService; 
        $this->file = ''; 
        $this->fileName = ''; 
        $this->otherData = []; 
        $this->extractData = []; 
        $this->isJson = false; 
        $this->pageService = $pageService; 
        $this->request = $requestStack->getCurrentRequest(); 
        $this->security = $security; 
        $this->template = self::DEFAULT_TEMPLATE; 
        $this->translationService = $translationService; 
        $this->translator = $translator; 
        self::$messagesFromService = []; 
        $reflection = new ReflectionClass(get_class($this)); 
        foreach ($reflection->getAttributes() as $attribute) { 
            if (isset($attribute->getArguments()['name'])) { 
                if ('Symfony\Component\Routing\Annotation\Route' === $attribute->getName()) { 
                    $this->routePrefix = $attribute->getArguments()['name']; 
                } else { 
                    switch ($attribute->getArguments()[0]) { 
                        case 'entity': 
                            $this->entityClass = $attribute->getArguments()['name']; 
                            $tabEntity = explode('\\', $this->entityClass); 
                            $this->entityName = end($tabEntity); 
                            break; 
                        case 'domain': 
                            $this->domain = $attribute->getArguments()['name']; 
                            break; 
                    } 
                } 
            } 
        } 
        $this->context = $context; 
    } 
 
    public function getResponse(): Response 
    { 
        $clinicDatas = ['sign' => null]; 
        if ($clinic = $this->getContext()->get('clinic')) { 
            $clinicDatas = [ 
                'sign' => $clinic->getSign(), 
                'slug' => $this->getParameter('prestashop.url') . '/mon-veterinaire/' . $clinic->getSlug(), 
                'hasShop' => $clinic->getClubvetShop(), 
                'hasWebSite' => $clinic->getClubvetWeb(), 
                'clinicSiteUrl' => $clinic->getClubvetWeb() ? $this->clinicService->getClinicDomain($clinic) : '', 
                'hasAdvPhoneNumber' => $this->clinicService->getClinicSalesman($clinic)?->getAdvPhoneNumber() ?? false, 
                'isVeterinary' => 
                    in_array('ROLE_VETERINARY', $this->getUser()->getRoles()) || 
                    in_array('ROLE_ASV_LIGHT', $this->getUser()->getRoles()) || 
                    in_array('ROLE_ASV', $this->getUser()->getRoles()), 
                'hasBusinessSoftware' => $this->security->isGranted('IS_IMPERSONATOR') ? true : (bool)$clinic->getBusinessSoftware(), 
            ]; 
        } 
        foreach (self::$messagesFromService as $message) { 
            $this->addStatus($message['text'], $message['severity'], $message['domain']); 
        } 
        if ($this->file && $this->fileName) { 
            $response = new Response($this->file); 
            $response->headers->set('Content-Disposition', HeaderUtils::makeDisposition( 
                $this->fileDisposition, 
                $this->fileName, preg_replace('#^.*\.#', md5($this->fileName) . '.', $this->fileName) 
            )); 
            if ($this->fileDisposition === HeaderUtils::DISPOSITION_INLINE) { 
                $fileName = explode('.', $this->fileName); 
                $response->headers->set('Content-Type', 'application/' . array_pop($fileName)); 
            } 
            return $response; 
        } 
        if ('fetch' === $this->request->headers->get('A-Sending-Method') || $this->isJson) { 
            if ( 
                str_contains($this->request->getRequestUri(), 'admin/clinic') && 
                str_contains($this->request->getRequestUri(), 'choose') && 
                !str_contains($this->request->getRequestUri(), 'choosePricePlan') 
            ) { 
                $this->setContent('searchClinicsUrl', $this->generateUrl('adminClinicSearchClinics')); 
                $this->setContent('a-switch-clinic', $clinicDatas); 
            } 
            if ($page = $this->getRepository(Page::class)->findOneByPath($this->request->getRequestUri())) { 
                $breadcrumb = []; 
                while ($page) { 
                    $breadcrumb[] = ['link' => $page->getPath(), 'label' => $this->translationService->getContent($page, 'label')]; 
                    $page = $page->getParent(); 
                } 
                $this->args[self::TAG_BREADCRUMB] = array_reverse($breadcrumb); 
            } 
            if ($this->security->getUser() === null) { 
                $response = $this->json(['a-reload' => true]); 
            } else { 
                if ('true' === $this->request->headers->get('A-Fetching-Menu')) { 
                    $this->setContent('a-pages', $this->pageService->getPages()); 
                } 
                if (self::DEFAULT_TEMPLATE != $this->template) { 
                    $this->args[self::TAG_MAIN] = $this->renderView( 
                        $this->template . self::TEMPLATE_EXTENSION, 
                        $this->args 
                    ); 
                } 
                if ( 
                    empty($this->args[self::TAG_PREVENT_URL_UPDATE]) 
                    && !empty($this->args[self::TAG_MAIN]) 
                ) { 
                    // display video tutorial, if any, in header 
                    $this->args[self::TAG_VIDEO_TUTORIAL] = $this->getVideoTutorialUrl(); 
                    if ($this->newDesign) { 
                        $this->addJS('document.body.classList.add(\'design-2025\');'); 
                    } else { 
                        $this->addJS('document.body.classList.remove(\'design-2025\');'); 
                    } 
                } 
//                if ($clinic 
//                    && $clinic->getClubvetShop() 
//                    && empty($this->args[self::TAG_MODAL_CONTENT]) 
//                    && empty($this->args[self::TAG_REDIRECT]) 
//                    && empty($this->args[self::TAG_REDIRECT_WITHOUT_LOADER]) 
//                    && !$this->request->cookies->get('alertHolidaySummer2025') 
//                ) { 
//                    $this->addCookie('alertHolidaySummer2025', '1'); 
//                    if ($this->request->get('_route') !== 'adminAdministrationHolidayIndex') { 
//                        $this->setModal( 
//                            'Vous partez aussi en vacances ?', 
//                            ' 
//                                <p class="mb-1">N’oubliez pas d’activer le mode vacances directement depuis votre espace vétérinaire ClubVET Shop afin d’avertir vos clients de votre absence.</p> 
//                                <p class="mb-1"> 
//                                    <span class="font-bold">Bon à savoir</span> : les commandes d’abonnement de vos clients, prévues pendant la période de fermeture de la clinique, seront annulées.<br/> 
//                                    Les clients sont informés par e-mail à deux reprises : une première fois lors de l’envoi de votre message de congés, puis une seconde fois lors de l’annulation automatique, 3 jours avant la date prévue de réception. 
//                                </p> 
//                                <p class="flex justify-between gap-2"> 
//                                    <a 
//                                        href="https://xs4xg.mjt.lu/nl3/IrJhnnAzmvnKaFmRsULMRQ?m=AUAAAU7EgGAAAAAAAAAAAKpkxpMAAAAAF1AAAAAAAA27zwBmqMe-pZ-NByaTSG-YlD08x2njaAANpOw&b=1e897e7e&e=dfc0cc58&x=clFl3uxmAix1csWcfeNWGg" 
//                                        target="_blank" 
//                                        class="bg-secondary text-center text-white rounded-lg align-middle cursor-pointer inline-flex items-center justify-center min-h-10 px-3" 
//                                    > 
//                                        <span class="material-symbols-outlined flex justify-center mr-2">help</span> 
//                                        Tutoriel 
//                                    </a> 
//                                    <a 
//                                        href="' . $this->generateUrl('adminAdministrationHolidayIndex') . '" 
//                                        a-click="fetch" 
//                                        a-modal="closer" 
//                                        class="bg-secondary text-center text-white rounded-lg align-middle cursor-pointer inline-flex items-center justify-center min-h-10 px-3" 
//                                    > 
//                                        <span class="material-symbols-outlined flex justify-center mr-2">beach_access</span> 
//                                        Activer le mode vacances 
//                                    </a> 
//                                ' 
//                        ); 
//                    } 
//                } 
                $response = $this->json($this->args); 
            } 
        } else { 
            if ($user = $this->security->getUser()) { 
                $this->args['user'] = [ 
                    'firstname' => $user->getFirstname(), 
                    'lastname' => $user->getLastname(), 
                    'avatar' => $user->getAvatar()?->getUrl(), 
                    'onboardingStep' => $user->getOnboardingStep(), 
                    'screenResolutions' => $user->getScreenResolutions(), 
                ]; 
            } 
            $this->setContent('searchClinicsUrl', $this->generateUrl('adminClinicSearchClinics')); 
            $this->setContent('a-switch-clinic', $clinicDatas); 
            $this->setContent('canEditVideoTutorial', $this->canEditVideoTutorial()); 
            $this->setContent('newDesign', $this->newDesign); 
            $response = $this->render( 
                $this->template . self::TEMPLATE_EXTENSION, 
                $this->args 
            ); 
        } 
        if (count($this->cookies)) { 
            try { 
                $expire = $this->dateService->getDate(interval: 'P1Y'); 
                foreach ($this->cookies as $name => $value) { 
                    $response->headers->setCookie(new Cookie($name, $value, $expire)); 
                } 
            } catch (Exception $exception) { 
                $this->addException($exception); 
            } 
        } 
 
        return $response; 
    } 
 
    public function setContent(string $key, mixed $content, ?array $args = null, ?string $domain = null): self 
    { 
        $this->args[$key] = (is_null($args) ? 
            (is_string($content) ? $this->trans($content, $domain) : $content) : 
            $this->renderView( 
                $content . self::TEMPLATE_EXTENSION, 
                $args 
            ) 
        ); 
 
        return $this; 
    } 
 
    public function setMain(string $content, ?array $args = null): self 
    { 
        return $this->setContent(self::TAG_MAIN, $content, $args); 
    } 
 
    public function setMainTitle(string $content, ?string $domain = null): self 
    { 
        return $this->setContent(self::TAG_MAIN_TITLE, $this->trans($content, $domain)); 
    } 
 
    public function hideMainTitle(): self 
    { 
        return $this->setContent(self::TAG_HIDE_MAIN_TITLE, true); 
    } 
 
    public function setMainSubTitle(string $content, ?string $domain = null): self 
    { 
        return $this->setContent(self::TAG_MAIN_SUBTITLE, $this->trans($content, $domain)); 
    } 
 
    public function setMainOverTitle(string $content, ?string $domain = null): self 
    { 
        return $this->setContent(self::TAG_MAIN_OVERTITLE, $this->trans($content, $domain)); 
    } 
 
    public function setRedirect(string $url): self 
    { 
        return $this->setContent(self::TAG_REDIRECT, $url); 
    } 
 
    public function setRedirectWithoutLoader(string $url): self 
    { 
        return $this->setContent(self::TAG_REDIRECT_WITHOUT_LOADER, $url); 
    } 
 
    public function setModal(string $title, string $content, ?array $args = null, ?string $domain = null): self 
    { 
        return $this 
            ->setContent(self::TAG_MODAL_TITLE, $this->trans($title, $domain)) 
            ->setContent(self::TAG_MODAL_CONTENT, $content, $args) 
            ->setContent(self::TAG_MODAL_CLOSABLE, true); 
    } 
 
    public function setUnclosableModal(string $title, string $content, ?array $args = null, ?string $domain = null): self 
    { 
        return $this 
            ->setContent(self::TAG_MODAL_TITLE, $this->trans($title, $domain)) 
            ->setContent(self::TAG_MODAL_CONTENT, $content, $args) 
            ->setContent(self::TAG_MODAL_CLOSABLE, false); 
    } 
 
    public function setWaitingModal(string $files, string $subject, string $body, bool $plural = false): self 
    { 
        return $this 
            ->addJS('Athena.programDeferredDeliveryCheck();') 
            ->setContent(self::TAG_MODAL_TITLE, ($plural ? 'Vos fichiers sont' : 'Votre fichier est') . ' en cours de préparation') 
            ->setcontent(self::TAG_MODAL_CONTENT, 'Athena/DeferredDelivery/waitingModal', [ 
                'files' => $files, 
                'plural' => $plural, 
                'subject' => $subject, 
                'body' => $body, 
            ]) 
            ->setContent(self::TAG_MODAL_CLOSABLE, false); 
    } 
 
    public function setSidebarModal(string $title, string $content, string $iconSb, ?array $args = null, ?string $domain = null): self 
    { 
        return $this 
            ->setContent(self::TAG_SIDEBAR_MODAL_TITLE, $this->trans($title, $domain)) 
            ->setContent(self::TAG_SIDEBAR_MODAL_CONTENT, $content, $args) 
            ->setContent(self::TAG_SIDEBAR_MODAL_ICON, $iconSb); 
    } 
 
    public function setError(string $title, string $content, ?array $args = null, ?string $domain = null): self 
    { 
        return $this 
            ->setContent(self::TAG_ERROR_TITLE, $this->trans($title, $domain)) 
            ->setContent(self::TAG_ERROR_CONTENT, $content, $args); 
    } 
 
    public function setTemplate(string $template): self 
    { 
        $this->template = $template; 
 
        return $this; 
    } 
 
    public function setReloadIframe(): self 
    { 
        $this->args[self::TAG_RELOAD_IFRAME] = true; 
 
        return $this; 
    } 
 
    /** 
     * @param $key string|array 
     * @param $value ?string 
     * @return $this 
     */ 
    public function setValue($key, $value = null): self 
    { 
        if (is_array($key)) { 
            $this->args[self::TAG_SET_VALUE] = json_encode($key); 
        } else { 
            $this->args[self::TAG_SET_VALUE] = json_encode(['key' => $key, 'value' => $value]); 
        } 
 
        return $this; 
    } 
 
    public function setInnerHTML(array $data): self 
    { 
        if (isset($this->args[self::TAG_SET_INNER_HTML])) { 
            $data = array_merge(json_decode($this->args[self::TAG_SET_INNER_HTML], true), $data); 
        } 
        $this->args[self::TAG_SET_INNER_HTML] = json_encode($data); 
 
        return $this; 
    } 
 
    public function preventUrlUpdate(): self 
    { 
        $this->args[self::TAG_PREVENT_URL_UPDATE] = true; 
 
        return $this; 
    } 
 
    public function addCookie(string $name, string $value): self 
    { 
        $this->cookies[$name] = $value; 
 
        return $this; 
    } 
 
    public function addStatus( 
        string  $message, 
        string  $type = self::STATUS_MESSAGE, 
        ?string $domain = null 
    ): self 
    { 
        if (!isset($this->args[self::TAG_STATUS])) { 
            $this->args[self::TAG_STATUS] = []; 
        } 
        $this->args[self::TAG_STATUS][] = [ 
            'text' => $this->trans($message, $domain), 
            'severity' => $type, 
        ]; 
 
        return $this; 
    } 
 
    public static function addStatusFromService( 
        string  $message, 
        string  $type = self::STATUS_MESSAGE, 
        ?string $domain = null 
    ): void 
    { 
        self::$messagesFromService[] = [ 
            'text' => $message, 
            'severity' => $type, 
            'domain' => $domain, 
        ]; 
    } 
 
    public function addButton( 
        string  $url, 
        string  $label, 
        string  $icon, 
        string  $class = '', 
        ?string $domain = null, 
        string  $wrapper = '', 
        bool    $fetch = true 
    ): self 
    { 
        if (!isset($this->args[self::TAG_BUTTONS])) { 
            $this->args[self::TAG_BUTTONS] = []; 
        } 
        $this->args[self::TAG_BUTTONS][] = [ 
            'url' => $url, 
            'label' => $this->trans($label, $domain), 
            'icon' => $icon, 
            'class' => $class, 
            'wrapper' => $wrapper, 
            'fetch' => $fetch, 
        ]; 
 
        return $this; 
    } 
 
    public function addException(Exception $exception): self 
    { 
        return $this->setError('Exception', $exception->getMessage()); 
    } 
 
    public function addJS(string $js): self 
    { 
        if (!isset($this->args[self::TAG_JAVASCRIPT])) { 
            $this->args[self::TAG_JAVASCRIPT] = ''; 
        } 
        $this->args[self::TAG_JAVASCRIPT] .= $js; 
 
        return $this; 
    } 
 
    public function getRepository(string $class): ObjectRepository 
    { 
        return $this->getDoctrine()->getManager()->getRepository($class); 
    } 
 
    public function persist(): self 
    { 
        foreach (func_get_args() as $entity) { 
            $this->getDoctrine()->getManager()->persist($entity); 
        } 
 
        return $this; 
    } 
 
    public function remove(): self 
    { 
        foreach (func_get_args() as $entity) { 
            $this->getDoctrine()->getManager()->remove($entity); 
        } 
 
        return $this; 
    } 
 
    public function clear(): self 
    { 
        foreach (func_get_args() as $entity) { 
            $this->getDoctrine()->getManager()->clear($entity); 
        } 
 
        return $this; 
    } 
 
    public function detach(): self 
    { 
        foreach (func_get_args() as $entity) { 
            $this->getDoctrine()->getManager()->detach($entity); 
        } 
 
        return $this; 
    } 
 
    public function flush(): self 
    { 
        if (count(func_get_args())) { 
            foreach (func_get_args() as $entity) { 
                $this->getDoctrine()->getManager()->flush($entity); 
            } 
        } else { 
            $this->getDoctrine()->getManager()->flush(); 
        } 
 
        return $this; 
    } 
 
    public function trans(string $string, string $domain = null, array $args = [], ?string $locale = null): string 
    { 
        return $this->translator->trans($string, $args, $domain, $locale); 
    } 
 
    public function keepModalOpened(): self 
    { 
        $this->args[self::TAG_KEEP_MODAL_OPENED] = true; 
        return $this; 
    } 
 
    public function keepSideBarModalOpened(): self 
    { 
        $this->args[self::TAG_KEEP_SIDEBAR_MODAL_OPENED] = true; 
        return $this; 
    } 
 
    public function scrollToTop(): self 
    { 
        $this->args[self::TAG_SCROLL_TO_TOP] = true; 
        return $this; 
    } 
 
    public function openOnboarding($datas): self 
    { 
        $this->args[self::TAG_ONBOARDING] = json_encode($datas); 
        return $this; 
    } 
 
    public function redirectByFetch(string $url): Response 
    { 
        return $this 
            ->setMain( 
                'Athena/redirect', 
                [ 
                    'url' => $url, 
                ] 
            ) 
            ->getResponse(); 
    } 
 
    public function redirectToRouteByFetch(string $route, array $parameters = []): Response 
    { 
        return $this->redirectByFetch($this->generateUrl($route, $parameters)); 
    } 
 
 
    #[Route('/', name: 'home')] 
    public function home(): Response 
    { 
        return $this->redirectToRoute('admin'); 
    } 
 
    #[Route('/admin', name: 'admin')] 
    public function admin(): Response 
    { 
        return $this->getResponse(); 
    } 
 
    #[Route('/health_check', name: 'healthCheck')] 
    public function healthCheck(?Profiler $profiler): Response 
    { 
        $profiler?->disable(); 
        $return = []; 
        try { 
            if (!$this->getRepository(User::class)->find(1)) { 
                throw new \Exception('Problème de connexion à la DB', 1, null); 
            } 
            $return['DB'] = 'OK'; 
        } catch (\Exception $e) { 
            return new Response(json_encode(['error' => $e->getCode(), 'message' => $e->getMessage(), 'line' => $e->getLine()]), 500); 
 
        } 
        return new Response(json_encode($return), 200); 
    } 
 
    public function handleGenericForm( 
        Request $request, 
        mixed   $object, 
        string  $type, 
        array   $optionsForRoute = [], 
        bool    $delete = false, 
        array   $options = [], 
        ?object $service = null, 
        ?string $preProcess = null, 
        ?string $postProcess = null, 
        ?string $updateProcess = null, 
        ?string $validateProcess = null, 
    ): object 
    { 
        if (is_string($object)) { 
            $object = new $object(); 
        } 
        $form = $this->createForm( 
            $type, 
            $object, 
            array_merge( 
                ['action' => $this->generateUrl($request->attributes->get('_route'), $optionsForRoute)], 
                $options 
            ) 
        ); 
        $form->handleRequest($request); 
 
        if ($form->isSubmitted()) { 
            if ($service && $validateProcess) { 
                $service->$validateProcess($object, $form); 
            } 
            if ($form->isValid()) { 
                if ($service && $preProcess) { 
                    try { 
                        $service->$preProcess($object, $form); 
                    } catch (\Exception $e) { 
                        $this->addException($e); 
                        return $form; 
                    } 
                } 
                if ($service && $updateProcess) { 
                    try { 
                        $service->$updateProcess($object, $form); 
                    } catch (\Exception $e) { 
                        $this->addException($e); 
                        return $form; 
                    } 
                } elseif ($object) { 
                    if ($delete) { 
                        $this->remove($object)->flush(); 
                    } else { 
                        $this->persist($object)->flush(); 
                    } 
                } 
                if ($service && $postProcess) { 
                    try { 
                        $service->$postProcess($object, $form, $this); 
                    } catch (\Exception $e) { 
                        $this->addException($e); 
                        return $form; 
                    } 
                } 
 
                return $object; 
            } 
        } 
 
        return $form; 
    } 
 
    public function getAvailableRoles(): array 
    { 
        $result = []; 
        foreach ($this->getParameter('security.role_hierarchy.roles') as $role => $roles) { 
            $result[$this->trans('User.controller.User.Roles.' . $role, 'Athena')] = $role; 
        } 
        krsort($result); 
 
        if (!$this->security->isGranted('ROLE_SUPER_ADMIN')) { 
            unset($result['ROLE_SUPER_ADMIN']); 
        } 
        return $result; 
    } 
 
    public function getTranslatedAvailableRoles(): array 
    { 
        $result = []; 
        foreach ($this->getParameter('security.role_hierarchy.roles') as $role => $roles) { 
            $result[$role] = $this->trans('User.controller.User.Roles.' . $role, 'Athena'); 
        } 
        ksort($result); 
 
        if (!$this->security->isGranted('ROLE_SUPER_ADMIN')) { 
            unset($result['ROLE_SUPER_ADMIN']); 
        } 
        return $result; 
    } 
 
    public function _datatableIndex( 
        string  $template = 'Athena/datatable', 
        bool    $addButton = true, 
        bool    $searchField = true, 
        array   $additionalButton = [], 
        ?string $getDatatableUrl = null, 
        ?string $createUrl = null 
    ): Response 
    { 
        // set filters from url 
        $search = $this->request->query->get('search'); 
        $filters = $this->request->query->get('filters'); 
        if ($search || $filters) { 
            $session = $this->request->getSession(); 
            $additionalSearchField = []; 
            $datatablesFilters = $session->get('datatablesFilters', []); 
            if (isset($datatablesFilters[$this->routePrefix])) { 
                $additionalSearchField = $datatablesFilters[$this->routePrefix]['additionalSearchField'] ?? []; 
            } 
            if ($filters) { 
                foreach ($filters as $field => $value) { 
                    if ('' !== $value) { 
                        $additionalSearchField[$field] = $value; 
                    } elseif (isset($additionalSearchField[$field])) { 
                        unset($additionalSearchField[$field]); 
                    } 
                } 
            } 
            $datatablesFilters[$this->routePrefix] = [ 
                'search' => $search ?: $datatablesFilters[$this->routePrefix]['search'] ?? '', 
                'additionalSearchField' => $additionalSearchField, 
            ]; 
            $session->set('datatablesFilters', $datatablesFilters); 
        } 
        $this 
            ->setMainTitle( 
                $this->translator->trans( 
                    $this->entityName . '.controller.' . $this->entityName . '.main_title', 
                    [], 
                    $this->domain 
                ) 
            ) 
            ->setMain( 
                $template, 
                [ 
                    'datatableUrl' => $getDatatableUrl ?: $this->generateUrl($this->routePrefix . 'GetDatatable'), 
                    'other' => $this->otherData, 
                    'searchField' => (int)$searchField 
                ] 
            ); 
 
        if ($addButton) { 
            $this->addButton( 
                $createUrl ?: $this->generateUrl($this->routePrefix . 'Create'), 
                $this->entityName . '.controller.' . $this->entityName . '.buttons.create', 
                'add_circle_outline', 
                '', 
                $this->domain 
            ); 
        } 
 
        if (!empty($additionalButton)) { 
            $this->addButton( 
                $additionalButton['url'] ?? '', 
                $additionalButton['text'] ?? '', 
                $additionalButton['icon'] ?? '', 
                '', 
                $this->domain 
            ); 
        } 
 
        return $this->getResponse(); 
    } 
 
 
    public function _datatable( 
        int             $page = 1, 
        int             $limit = 1, 
        string          $sort = 'none', 
        string          $search = '', 
        string          $datatableTemplate = 'Default', 
        ?ContextService $context = null, 
        ?array          $preLoadedDatas = null, 
        string          $templateForPreload = '', 
        array           $optionsForPreload = [], 
        array           $additionalSearchField = [], 
        int             $countForPreload = -1 
    ): Response 
    { 
        // restore or save filters in session 
        $session = $this->request->getSession(); 
        $datatablesFilters = $session->get('datatablesFilters', []); 
        if ($this->request->get('firstLoad', false)) { 
            if (isset($datatablesFilters[$this->routePrefix])) { 
                $search = $datatablesFilters[$this->routePrefix]['search'] ?? ''; 
                $additionalSearchField = $datatablesFilters[$this->routePrefix]['additionalSearchField'] ?? []; 
            } 
        } else { 
            $datatablesFilters[$this->routePrefix] = [ 
                'search' => $search, 
                'additionalSearchField' => $additionalSearchField, 
            ]; 
            $session->set('datatablesFilters', $datatablesFilters); 
        } 
 
        $this->setContent( 
            'entity', 
            $this->translator->trans( 
                $this->entityName . '.template.index.entity.plural', 
                [], 
                $this->domain 
            ) 
        ); 
        $datatable = $this->datatableService->buildDatatable( 
            $this->entityClass, 
            $page, 
            $limit, 
            $sort, 
            $search, 
            $datatableTemplate, 
            $context, 
            $preLoadedDatas, 
            $templateForPreload, 
            $optionsForPreload, 
            $additionalSearchField, 
            $countForPreload 
        ); 
        foreach ($datatable as $key => $val) { 
            $this->setContent($key, $val); 
        } 
 
        return $this->getResponse(); 
    } 
 
    public function _create( 
        Request $request, 
        string  $formClass, 
        array   $optionsForRoute = [], 
        bool    $delete = false, 
        array   $options = [], 
        ?object $service = null, 
        ?string $preProcess = null, 
        ?string $postProcess = null, 
        ?string $updateProcess = null, 
        ?string $validateProcess = null, 
        bool    $modal = true, 
        string  $content = 'Athena/genericType', 
        array   $args = [], 
        bool    $returnRequest = false, 
        string  $postUpdateMessage = null, 
        string  $postUpdateStatus = null, 
        array   $buttonAttribute = [], 
        ?string $entityName = null, 
        ?object $object = null, 
        ?string $postRedirectUrl = null, 
    ) 
    { 
        $return = $this->handleGenericForm( 
            $request, 
            $object ?: $this->entityClass, 
            $formClass, 
            $optionsForRoute, 
            $delete, 
            $options, 
            $service, 
            $preProcess, 
            $postProcess, 
            $updateProcess, 
            $validateProcess 
        ); 
        if ($return instanceof $this->entityClass) { 
            if ($postUpdateMessage) { 
                $this->addStatus($postUpdateMessage, $postUpdateStatus ?? self::STATUS_MESSAGE); 
            } 
            if ($postRedirectUrl) { 
                return $this 
                    ->setRedirect($postRedirectUrl) 
                    ->getResponse(); 
            } elseif ($returnRequest) { 
                return $this->index($request); 
            } else { 
                return $this->index(); 
            } 
        } else { 
            if ($modal) { 
                $this->setModal( 
                    ($entityName ?? $this->entityName) . '.controller.' . ($entityName ?? $this->entityName) . '.modal.createTitle', 
                    $content, 
                    array_merge($args, ['form' => $return->createView(), 'entity' => ($entityName ?? $this->entityName)]), 
                    $this->domain 
                ); 
            } else { 
                $this->setMainTitle( 
                    $this->translator->trans( 
                        $this->entityName . '.controller.' . $this->entityName . '.main.createTitle', 
                        [], 
                        $this->domain 
                    ) 
                ) 
                    ->setMain( 
                        $content, 
                        array_merge($args, ['form' => $return->createView(), 'entity' => $this->entityName]) 
                    ); 
                if ($buttonAttribute && !empty($buttonAttribute)) { 
                    $this->addButton( 
                        $this->generateUrl($buttonAttribute['url']), 
                        $this->entityName . '.controller.' . $this->entityName . '.buttons.' . $buttonAttribute['label'], 
                        $buttonAttribute['icon'], 
                        $buttonAttribute['class'], 
                        $buttonAttribute['transDomain'] 
                    ); 
                } 
            } 
            return $this->getResponse(); 
        } 
    } 
 
    public function _update( 
        Request $request, 
        object  $object, 
        string  $formClass, 
        array   $optionsForRoute = [], 
        bool    $delete = false, 
        array   $options = [], 
        ?object $service = null, 
        ?string $preProcess = null, 
        ?string $postProcess = null, 
        ?string $updateProcess = null, 
        ?string $validateProcess = null, 
        bool    $modal = true, 
        string  $content = 'Athena/genericType', 
        array   $args = [], 
        bool    $returnRequest = false, 
        string  $postUpdateMessage = null, 
        string  $postUpdateStatus = null, 
        ?string $entityName = null, 
        ?string $postRedirectUrl = null, 
    ): Response 
    { 
        $return = $this->handleGenericForm( 
            $request, 
            $object, 
            $formClass, 
            $optionsForRoute, 
            $delete, 
            $options, 
            $service, 
            $preProcess, 
            $postProcess, 
            $updateProcess, 
            $validateProcess 
        ); 
        if ($return instanceof $this->entityClass) { 
            if ($postUpdateMessage) { 
                $this->addStatus($postUpdateMessage, $postUpdateStatus ?? self::STATUS_MESSAGE); 
            } 
            if ($postRedirectUrl) { 
                return $this 
                    ->setRedirect($postRedirectUrl) 
                    ->getResponse(); 
            } elseif ($returnRequest) { 
                return $this->index($request); 
            } else { 
                return $this->index(); 
            } 
        } else { 
            if ($modal) { 
                $this 
                    ->setModal( 
                        ($entityName ?? $this->entityName) . '.controller.' . ($entityName ?? $this->entityName) . '.modal.updateTitle', 
                        $content, 
                        array_merge($args, ['form' => $return->createView(), 'entity' => ($entityName ?? $this->entityName)]), 
                        $this->domain 
                    ); 
            } else { 
                $this->setMainTitle( 
                    $this->translator->trans( 
                        $this->entityName . '.controller.' . $this->entityName . '.main.updateTitle', 
                        [], 
                        $this->domain 
                    ) 
                ) 
                    ->setMain( 
                        $content, 
                        array_merge($args, ['form' => $return->createView(), 'entity' => $this->entityName]) 
                    ); 
            } 
 
            return $this->getResponse(); 
        } 
    } 
 
    public function _delete( 
        Request $request, 
        object  $object, 
                $optionsForRoute, 
        string  $postUpdateMessage = null, 
        string  $postUpdateStatus = null, 
        array   $options = [], 
        ?object $service = null, 
        ?string $preProcess = null, 
        ?string $postProcess = null, 
        ?string $updateProcess = null, 
        ?string $validateProcess = null, 
        bool    $returnRequest = false, 
        ?string $entityName = null, 
        ?string $postRedirectUrl = null, 
    ) 
    { 
 
        if (($return = $this->handleGenericForm( 
                $request, 
                $object, 
                DeleteForm::class, 
                $optionsForRoute, 
                true, 
                $options, 
                $service, 
                $preProcess, 
                $postProcess, 
                $updateProcess, 
                $validateProcess 
            )) instanceof $this->entityClass) { 
            if ($postUpdateMessage) { 
                $this->addStatus($postUpdateMessage, $postUpdateStatus ?? self::STATUS_MESSAGE); 
            } 
            if ($postRedirectUrl) { 
                return $this 
                    ->setRedirect($postRedirectUrl) 
                    ->getResponse(); 
            } elseif ($returnRequest) { 
                return $this->index($request); 
            } else { 
                return $this->index(); 
            } 
        } else { 
            return $this 
                ->setModal( 
                    ($entityName ?? $this->entityName) . '.controller.' . ($entityName ?? $this->entityName) . '.modal.deleteTitle', 
                    'Athena/deleteType', 
                    [ 
                        'form' => $return->createView(), 
                        'entity' => $this->translator->trans( 
                            ($entityName ?? $this->entityName) . '.controller.' . ($entityName ?? $this->entityName) . '.modal.entity', 
                            [], 
                            $this->domain 
                        ), 
                    ], 
                    $this->domain 
                ) 
                ->getResponse(); 
        } 
    } 
 
    public function _autocomplete(string $search, ?string $entityClass = null): JsonResponse 
    { 
        $result = array(); 
        if ($search) { 
            foreach ($this->getRepository($entityClass ?? $this->entityClass)->getAutocomplete($search) as $object) { 
                $result[] = ['id' => $object->getId(), 'text' => $object->_toAutocomplete()]; 
            } 
        } 
        return $this->json($result); 
    } 
 
    public function _show( 
        string $content, 
        bool   $modal = false, 
        array  $args = [], 
        array  $translateParameters = [] 
    ): Response 
    { 
        if ($modal) { 
            $this 
                ->setModal( 
                    $this->entityName . '.controller.' . $this->entityName . '.modal.showTitle', 
                    $content, 
                    array_merge($args, ['entity' => $this->entityName]), 
                    $this->domain 
                ); 
        } else { 
            $this->setMainTitle( 
                $this->translator->trans( 
                    $this->entityName . '.controller.' . $this->entityName . '.main.showTitle', 
                    $translateParameters, 
                    $this->domain 
                ) 
            ) 
                ->setMain( 
                    $content, 
                    array_merge($args, ['entity' => $this->entityName]) 
                ); 
        } 
 
        return $this->getResponse(); 
    } 
 
    public function getContext(): ContextService 
    { 
        return $this->context; 
    } 
 
    public function setTargetBlank(string $url, ?array $args = null): self 
    { 
        return $this->setContent(self::TAG_TARGET_BLANK, $url, $args); 
    } 
 
    public function setFormTargetBlank(string $url, string $datas, ?array $args = null): self 
    { 
        return $this 
            ->setContent(self::TAG_FORM_BLANK, $url, $args) 
            ->setContent(self::TAG_FORM_BLANK_DATAS, $datas, $args); 
    } 
 
    public function setFunctionOnLoad(string $function): self 
    { 
        return $this->setContent(self::TAG_FUNCTION_ON_LOAD, $function); 
    } 
 
    public function _extract( 
        Request $request, 
        mixed   $class = '', 
        string  $filename = '', 
        string  $search = '', 
        array   $additionalSearchFields = [], 
        string  $datatableTemplate = '', 
                $context = null 
    ) 
    { 
        if (is_array($class)) { 
            $object = $class['data']; 
            if (isset($request->request->all()['extract_fields'])) { 
                $columns = []; 
                foreach ($request->request->all() as $key => $value) { 
                    if ($key !== 'extract_fields' && $value == 'on') { 
                        $columns[] = $this->trans($key, 'fields'); 
                    } 
                } 
                if (empty($columns)) { 
                    return $this->addStatus("Vous devez sélectionner une colonne pour l'extraction!", self::STATUS_ERROR)->setRedirect($this->generateUrl($this->routePrefix . 'Index'))->getResponse(); 
                } else { 
                    $res = $this->datatableService->filterArray($object, $columns); 
                    foreach ($res as &$line) { 
                        foreach ($line as $key => $val) { 
                            if (isset($class['options']['extract']['fields'][$key])) { 
                                $line[$this->trans($class['options']['extract']['fields'][$key], 'fields')] = $val; 
                                unset($line[$key]); 
                            } 
                        } 
                    } 
                    $fileName = $this->datatableService->export_data_to_csv($res, $filename); 
                    $this->setTargetBlank($this->generateUrl($this->routePrefix . 'DownloadExtract', ['filename' => $fileName])); 
 
                    return $this->addStatus("Le fichier a bien été téléchargé!", self::STATUS_MESSAGE)->setRedirect($this->generateUrl($this->routePrefix . 'Index')) 
                        ->getResponse(); 
                } 
            } 
            $params = ''; 
            foreach ($additionalSearchFields as $param) { 
                $params = $params . '/' . $param; 
            } 
            if (!empty($search)) { 
                $params = $params . '/' . $search; 
            } 
            return $this 
                ->setModal( 
                    $this->entityName . '.controller.' . $this->entityName . '.modal.extractTitle', 
                    'Athena/extractFields', 
                    [ 
                        'url' => $this->generateUrl($this->routePrefix . 'Extract') . $params, 
                        'options' => $class['options'] 
                    ], 
                    $this->domain 
                ) 
                ->getResponse(); 
        } else { 
            $object = new $class; 
            if (isset($request->request->all()['extract_fields'])) { 
                $columns = []; 
                foreach ($request->request->all() as $key => $value) { 
                    if ($key !== 'extract_fields' && $value == 'on') { 
                        $columns[] = $key; 
                    } 
                } 
                if (empty($columns)) { 
                    return $this->addStatus("Vous devez sélectionner une colonne pour l'extraction!", self::STATUS_ERROR)->setRedirect($this->generateUrl($this->routePrefix . 'Index'))->getResponse(); 
                } else { 
                    $dat = $this->getRepository($class)->getDatatableForDownload($search, $datatableTemplate, $context, $additionalSearchFields); 
                    $arrayDat = $this->datatableService->entityToArray($dat, $columns, $class); 
 
                    $fileName = $this->datatableService->export_data_to_csv($arrayDat, $filename); 
                    $this->setTargetBlank($this->generateUrl($this->routePrefix . 'DownloadExtract', ['filename' => $fileName])); 
 
                    return $this->addStatus("Le fichier a bien été téléchargé!", self::STATUS_MESSAGE)->setRedirect($this->generateUrl($this->routePrefix . 'Index')) 
                        ->getResponse(); 
                } 
            } 
            $params = ''; 
            foreach ($additionalSearchFields as $param) { 
                $params = $params . '/' . $param; 
            } 
            if (!empty($search)) { 
                $params = $params . '/' . $search; 
            } 
            return $this 
                ->setModal( 
                    $this->entityName . '.controller.' . $this->entityName . '.modal.extractTitle', 
                    'Athena/extractFields', 
                    [ 
                        'url' => $this->generateUrl($this->routePrefix . 'Extract') . $params, 
                        'options' => $object->_getMetadataDefault() 
                    ], 
                    $this->domain 
                ) 
                ->getResponse(); 
        } 
    } 
 
    public function handleS3Files(array $datas, string $subject, string $body): Response 
    { 
        if (isset($datas['s3Files'])) { 
            $this->setFormTargetBlank($this->generateUrl('adminAwsS3Download'), json_encode($datas)); 
        } elseif (isset($datas['files'])) { 
            $this->setWaitingModal(json_encode($datas['files']), $subject, $body); 
        } else { 
            $this->addStatus('Une erreur est survenue lors de la création du fichier : ' . print_r($datas, 1), self::STATUS_ERROR); 
        } 
        return $this->getResponse(); 
    } 
 
    /** 
     * @return false|string 
     */ 
    public function getVideoTutorialUrl(?string $route = null): string|false 
    { 
        $route ??= $this->request->attributes->get('_route'); 
        $videoTutorial = $this->getRepository(VideoTutorial::class)->findOneByRoute($route); 
        return $videoTutorial ? $this->generateUrl( 
            'adminVideoViewerIndex', 
            [ 
                'videoUrl' => $videoTutorial->getUrl(), 
                'title' => $videoTutorial->getTitle() ?: 'Tutoriel vidéo', 
            ] 
        ) : false; 
    } 
 
    private function canEditVideoTutorial(): string 
    { 
 
        $user = $this->getUser(); 
        if ($this->security->isGranted('IS_IMPERSONATOR')) { 
            $user = $this->security->getToken()->getOriginalToken()->getUser(); 
        } 
 
        return in_array('ROLE_SUPER_ADMIN', $user?->getRoles(), true) ? '1' : '0'; 
    } 
 
    public function setNewDesign(): self 
    { 
        $this->newDesign = true; 
        return $this; 
    } 
}