<?php

namespace App\Controller\CRUD;

use Sonata\AdminBundle\Controller\CRUDController as Controller;
use Sonata\AdminBundle\Datagrid\ProxyQueryInterface;
use Symfony\Component\Form\FormRenderer;
use Symfony\Component\Form\FormView;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use App\Utils\CustomEntityManager;
use App\Entity\User;
use App\Entity\Flux;

class CRUDController extends Controller
{

    protected $em;

    public function __construct(CustomEntityManager $em)
    {
        $this->em = $em;
    }

    /**
     * Create action.
     *
     * @throws AccessDeniedException If access is not granted
     *
     * @return Response
     */
    public function createAction()
    {
        $request = $this->getRequest();
        // the key used to lookup the template
        $templateKey = 'edit';

        $this->admin->checkAccess('create');

        $class = new \ReflectionClass($this->admin->hasActiveSubClass() ? $this->admin->getActiveSubClass() : $this->admin->getClass());

        if ($class->isAbstract()) {
            return $this->renderWithExtraParams(
                '@SonataAdmin/CRUD/select_subclass.html.twig',
                [
                    'base_template' => $this->getBaseTemplate(),
                    'admin' => $this->admin,
                    'action' => 'create',
                ],
                null
            );
        }

        $newObject = $this->admin->getNewInstance();

        $preResponse = $this->preCreate($request, $newObject);
        if (null !== $preResponse) {
            return $preResponse;
        }

        $this->admin->setSubject($newObject);

        $form = $this->admin->getForm();

        $form->setData($newObject);
        $form->handleRequest($request);

        if ($form->isSubmitted()) {
            $isFormValid = $form->isValid();

            // persist if the form was valid and if in preview mode the preview was approved
            if ($isFormValid && (!$this->isInPreviewMode() || $this->isPreviewApproved())) {
                /** @phpstan-var T $submittedObject */
                $submittedObject = $form->getData();
                $this->admin->setSubject($submittedObject);
                $this->admin->checkAccess('create', $submittedObject);

                try {
                    $newObject = $this->admin->create($submittedObject);

                    if ($this->isXmlHttpRequest()) {
                        return $this->handleXmlHttpRequestSuccessResponse($request, $newObject);
                    }
                    // ADD FOR KOHINOS => test if object newly created is null to send flash message success !
                    if (null != $newObject) {
                        $this->addFlash(
                            'sonata_flash_success',
                            $this->trans(
                                'flash_create_success',
                                ['%name%' => $this->escapeHtml($this->admin->toString($newObject))],
                                'SonataAdminBundle'
                            )
                        );
                    }

                    // redirect to edit mode
                    return $this->redirectTo($newObject);
                } catch (ModelManagerException $e) {
                    $this->handleModelManagerException($e);

                    $isFormValid = false;
                }
            }

            // show an error message if the form failed validation
            if (!$isFormValid) {
                if ($this->isXmlHttpRequest() && null !== ($response = $this->handleXmlHttpRequestErrorResponse($request, $form))) {
                    return $response;
                }

                $this->addFlash(
                    'sonata_flash_error',
                    $this->trans(
                        'flash_create_error',
                        ['%name%' => $this->escapeHtml($this->admin->toString($newObject))],
                        'SonataAdminBundle'
                    )
                );
            } elseif ($this->isPreviewRequested()) {
                // pick the preview template if the form was valid and preview was requested
                $templateKey = 'preview';
                $this->admin->getShow();
            }
        }

        $formView = $form->createView();
        // set the theme for the current Admin Form
        $this->setFormTheme($formView, $this->admin->getFormTheme());

        // NEXT_MAJOR: Remove this line and use commented line below it instead
        $template = $this->admin->getTemplate($templateKey);
        // $template = $this->templateRegistry->getTemplate($templateKey);

        return $this->renderWithExtraParams($template, [
            'action' => 'create',
            'form' => $formView,
            'object' => $newObject,
            'objectId' => null,
        ], null);
    }


    /**
     * Export data to specified format.
     *
     * @throws AccessDeniedException If access is not granted
     * @throws \RuntimeException     If the export format is invalid
     *
     */
    public function exportAction(Request $request)
    {
        set_time_limit(300); //set php time limit to 5 minutes to make sure big exports can be done
        $this->admin->checkAccess('export');

        $format = $request->get('format');

        // NEXT_MAJOR: remove the check
        if (!$this->has('sonata.admin.admin_exporter')) {
            @trigger_error(
                'Not registering the exporter bundle is deprecated since version 3.14. You must register it to be able to use the export action in 4.0.',
                \E_USER_DEPRECATED
            );
            $allowedExportFormats = (array) $this->admin->getExportFormats();

            $class = (string) $this->admin->getClass();
            $filename = sprintf(
                'export_%s_%s.%s',
                strtolower((string) substr($class, strripos($class, '\\') + 1)),
                date('Y_m_d_H_i_s', strtotime('now')),
                $format
            );
            $exporter = $this->get('sonata.admin.exporter');
        } else {
            $adminExporter = $this->get('sonata.admin.admin_exporter');
            $allowedExportFormats = $adminExporter->getAvailableFormats($this->admin);
            $filename = $adminExporter->getExportFilename($this->admin, $format);
            $exporter = $this->get('sonata.exporter.exporter');
        }

        if (!\in_array($format, $allowedExportFormats, true)) {
            throw new \RuntimeException(sprintf(
                'Export in format `%s` is not allowed for class: `%s`. Allowed formats are: `%s`',
                $format,
                $this->admin->getClass(),
                implode(', ', $allowedExportFormats)
            ));
        }

        return $exporter->getResponse(
            $format,
            $filename,
            $this->admin->getDataSourceIterator()
        );
    }


    public function deleteAction($id)
    {
        $request = $this->getRequest();
        $id = $request->get($this->admin->getIdParameter());
        $object = $this->admin->getObject($id);

        if (!$object) {
            throw $this->createNotFoundException(sprintf('unable to find the object with id: %s', $id));
        }

        $currentUserId = $this->getUser()->getId(); // ID of the current user
        if ($currentUserId == $id) {
            $this->addFlash(
                'sonata_flash_error',
                'Vous ne pouvez pas supprimer votre compte !'
            );

            return $this->redirectTo($object);
        }
        if ($object->hasRole('ROLE_SUPER_ADMIN') || $object->hasRole('ROLE_ADMIN_SIEGE')) {
            $this->addFlash(
                'sonata_flash_error',
                'Vous ne pouvez pas supprimer le compte admin !'
            );

            return $this->redirectTo($object);
        }
        if ($object->hasRole('ROLE_API')) {
            $this->addFlash(
                'sonata_flash_error',
                'Vous ne pouvez pas supprimer le compte API !'
            );

            return $this->redirectTo($object);
        }

        // Prevent deleting user if flux related to its Adherent account exist
        if ($object instanceof User)  {
            $query = $this->em->getRepository(Flux::class)->getQueryByUser($object);

            $hasFluxAdherent = false;
            if ($object->getAdherent()) {
                $queryAdherent = $this->em->getRepository(Flux::class)->getQueryByAdherent($object->getAdherent());
                if (null != $queryAdherent && count($queryAdherent->getResult()) > 0) {
                    $hasFluxAdherent = true;
                }
            }

            if (null != $query && count($query->getResult()) > 0 || $hasFluxAdherent) {
                $this->addFlash(
                    'sonata_flash_error',
                    'Vous ne pouvez pas supprimer ce compte utilisateur : des flux en relation à son compte sont enregistrés.'
                );

                return $this->redirectTo($object);
            }
        }

        return parent::deleteAction($id);
    }

    public function batchActionDelete(ProxyQueryInterface $query)
    {
        $request = $this->getRequest();
        $currentUserId = $this->getUser()->getId(); // ID of the current user
        $selectedUsers = $query->execute();

        foreach ($selectedUsers as $selectedUser) {
            if ($selectedUser->getId() == $currentUserId) {
                $this->addFlash(
                    'sonata_flash_error',
                    'Vous ne pouvez pas supprimer votre compte !'
                );

                return new RedirectResponse(
                    $this->admin->generateUrl('list', ['filter' => $this->admin->getFilterParameters()])
                );
            }
            if ($selectedUser->hasRole('ROLE_SUPER_ADMIN') || $selectedUser->hasRole('ROLE_ADMIN_SIEGE')) {
                $this->addFlash(
                    'sonata_flash_error',
                    'Vous ne pouvez pas supprimer le compte admin !'
                );

                return new RedirectResponse(
                    $this->admin->generateUrl('list', ['filter' => $this->admin->getFilterParameters()])
                );
            }
        }

        return parent::batchActionDelete($query);
    }

    /**
     * Sets the admin form theme to form view. Used for compatibility between Symfony versions.
     */
    private function setFormTheme(FormView $formView, ?array $theme = null): void
    {
        $twig = $this->get('twig');

        $twig->getRuntime(FormRenderer::class)->setTheme($formView, $theme);
    }
}
