<?php

declare(strict_types=1);

namespace App\Controller\Admin\Security\Utilisateurs;

use App\Entity\Security\Utilisateurs\Utilisateurs;
use App\Form\Security\Users\UtilisateursType;
use App\Interfaces\NotificationsInterface;
use App\Managers\ManagersInterface;
use App\Repository\Security\Utilisateurs\UtilisateursRepository;
use Exception;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security as Security;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;

#[Route('/admin/utilisateurs')]
#[Security("is_granted('ROLE_SUPER_ADMIN') or is_granted('ROLE_ADMIN') or is_granted('ROLE_USER')")]
class AdminUtilisateursController extends AbstractController
{
    public function __construct(
        private ManagersInterface $managers,
        private UserPasswordHasherInterface $encoder,
        private NotificationsInterface $notification,
    ) {}

    #[Route('/', name: "admin.utilisateurs.index", methods: ['GET'])]
    #[Security("is_granted('ROLE_SUPER_ADMIN') or is_granted('ROLE_ADMIN')")]
    /**
     * @param UtilisateursRepository $utilisateursRepository
     * @return Response
     */
    public function index(UtilisateursRepository $utilisateursRepository): Response
    {
        $this->denyAccessUnlessGranted('IS_AUTHENTICATED_FULLY');
        $utilisateur = new Utilisateurs();
        $form = $this->createForm(UtilisateursType::class, $utilisateur, ['user' => $utilisateur]);
        return $this->render('admin/security/users/utilisateurs/index.html.twig', [
            'utilisateurs' => $utilisateursRepository->findBy(['deletedAt' => null], ['id' => 'DESC']),
            'utilisateur' => $utilisateur,
            'user' => $utilisateur,
            'form' => $form->createView(),
            'title' => 'Liste des utilisateurs',
            'libelle_ajouter' => 'Nouvel utilisateur',
            'current_page' => 'utilisateurs',
            'current_global' => 'admin_users'
        ]);
    }

    #[Route('/show/{id<\d+>}', name: "admin.utilisateurs.show", methods: ['GET'])]
    #[Security("is_granted('ROLE_SUPER_ADMIN') or is_granted('ROLE_ADMIN')")]
    /**
     * @param Utilisateurs $utilisateur
     * @return Response
     */
    public function show(Utilisateurs $utilisateur): Response
    {
        $this->denyAccessUnlessGranted('IS_AUTHENTICATED_FULLY');
        return $this->render('admin/security/users/utilisateurs/show.html.twig', [
            'utilisateur' => $utilisateur,
            'title' => 'Détails utilisateur',
            'libelle_liste' => 'Liste des utilisateurs',
            'libelle_ajouter' => 'Nouvel utilisateur',
            'current_page' => 'utilisateurs',
            'current_global' => 'admin_users'
        ]);
    }

    #[Route('/new', name: "admin.utilisateurs.new", methods: ['GET', 'POST'])]
    #[Security("is_granted('ROLE_SUPER_ADMIN') or is_granted('ROLE_ADMIN')")]
    /**
     * @param Request $request
     * @return Response
     * @throws Exception
     *
     */
    public function new(Request $request): Response
    {
        $this->denyAccessUnlessGranted('IS_AUTHENTICATED_FULLY');
        $utilisateur = new Utilisateurs();
        $form = $this->createForm(UtilisateursType::class, $utilisateur, ['user' => $utilisateur]);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $this->managers->setEntity($utilisateur, 'new');
            $this->sendNotif('Utilisateur crée', 'Création', $utilisateur, 'check', 'green');
            $this->addFlash('success', 'Utilisateur crée avec succès.');
            return $this->redirectToRoute('admin.utilisateurs.new');
        }

        return $this->render('admin/security/users/utilisateurs/new.html.twig', [
            'utilisateur' => $utilisateur,
            'user' => $utilisateur,
            'form' => $form->createView(),
            'title' => 'Ajouter un nouvel utilisateur',
            'libelle_liste' => 'Liste des utilisateurs',
            'current_page' => 'utilisateurs_new',
            'current_global' => 'admin_users'
        ]);
    }

    #[Route('/{id<\d+>}/edit', name: "admin.utilisateurs.edit", methods: ['GET', 'POST'])]
    #[Security("is_granted('ROLE_SUPER_ADMIN') or is_granted('ROLE_ADMIN')")]
    /**
     * @param Request $request
     * @param Utilisateurs $utilisateur
     * @return Response
     * @throws Exception
     */
    public function edit(Request $request, Utilisateurs $utilisateur): Response
    {
        $this->denyAccessUnlessGranted('IS_AUTHENTICATED_FULLY');
        $form = $this->createForm(UtilisateursType::class, $utilisateur, ['user' => $utilisateur]);
        $form->handleRequest($request);
        if ($form->isSubmitted()) {
            /** @var string[] $datas */
            $datas = $request->request->all('utilisateurs');
            $currentPassword = $datas['password_actuel'];
            if ($currentPassword !== '') {
                $match = $this->encoder->isPasswordValid($utilisateur, (string)$currentPassword);
                if ($match) {
                    $firstNewPassword = $datas['plainPassword']['first'];
                    $confirmPassword = $datas['plainPassword']['second'];
                    if ($firstNewPassword === $confirmPassword) {
                        $this->encodeUserPassword($utilisateur, $confirmPassword);
                        //Connexion automatique
                        $token = new UsernamePasswordToken(
                            $utilisateur,
                            'main',
                            $utilisateur->getRoles()
                        );
                        $this->get('security.token_storage')->setToken($token);
                        $this->get('session')->set('_security_main', serialize($token));
                    } else {
                        $this->addFlash("danger", "Mot de passe non identique.");
                        return $this->redirectToRoute('admin.utilisateurs.edit', [
                            'id' => $utilisateur->getId(),
                        ]);
                    }
                } else {
                    $this->addFlash("danger", "Mot de passe actuel invalide.");
                    return $this->redirectToRoute('admin.utilisateurs.edit', [
                        'id' => $utilisateur->getId(),
                    ]);
                }
            }
            $this->managers->setEntity($utilisateur, 'edit');
            $this->sendNotif('Utilisateur modifié', 'Modification', $utilisateur, 'check', 'green');
            $this->addFlash('success', 'Utilisateur modifié avec succès.');
            return $this->redirectToRoute('admin.utilisateurs.edit', [
                'id' => $utilisateur->getId(),
                '_locale' => $request->get('_locale')
            ]);
        }

        return $this->render('admin/security/users/utilisateurs/edit.html.twig', [
            'utilisateur' => $utilisateur,
            'user' => $utilisateur,
            'form' => $form->createView(),
            'title' => 'Editer mon compte',
            'libelle_ajouter' => 'Nouveau utilisateur',
            'libelle_liste' => 'Liste des utilisateurs',
            'current_page' => 'utilisateurs',
            'current_global' => 'admin_users'
        ]);
    }

    #[Route('/compte/{id<\d+>}/edit', name: "admin.utilisateurs.compte.edit", methods: ['GET', 'POST'])]
    /**
     * @param Request $request
     * @param Utilisateurs $utilisateur
     * @return Response
     */
    public function editCompte(Request $request, Utilisateurs $utilisateur): Response
    {
        $this->denyAccessUnlessGranted('IS_AUTHENTICATED_FULLY');
        $form = $this->createForm(
            \App\Form\Security\Comptes\UtilisateursType::class,
            $utilisateur,
            ['user' => $utilisateur]
        );
        $form->handleRequest($request);
        if ($form->isSubmitted()) {
            $this->managers->setEntity($utilisateur, 'edit');
            $this->addFlash('success', 'Modification effectuée avec succès.');
            return $this->redirectToRoute('admin.utilisateurs.compte.edit', [
                'id' => $utilisateur->getId(),
                '_locale' => $request->get('_locale')
            ]);
        }

        return $this->render('admin/security/users/utilisateurs/compte.html.twig', [
            'utilisateur' => $utilisateur,
            'user' => $utilisateur,
            'form' => $form->createView(),
            'title' => 'Editer mon compte',
            'current_page' => 'comptes',
            'current_global' => 'comptes'
        ]);
    }

    #[Route('/{id<\d+>}', name: "admin.utilisateurs.delete", methods: ['DELETE'])]
    #[Security("is_granted('ROLE_SUPER_ADMIN') or is_granted('ROLE_ADMIN')")]
    /**
     * @param Request $request
     * @param Utilisateurs $utilisateur
     * @return Response
     * @throws Exception
     */
    public function delete(Request $request, Utilisateurs $utilisateur): Response
    {
        $this->denyAccessUnlessGranted('IS_AUTHENTICATED_FULLY');
        if ($this->isCsrfTokenValid('delete' . $utilisateur->getId(), $request->request->get('_token'))) {
            $this->sendNotif('Utilisateur supprimé', 'Suppression', $utilisateur, 'trash', 'red');
            $this->managers->setEntity($utilisateur, 'delete');
            $this->addFlash('success', 'Utilisateur supprimé avec succès.');
        }

        $referer = $request->headers->get('referer');
        return new RedirectResponse($referer ?? $this->generateUrl('admin.utilisateurs.index'));
    }

    /**
     * @param Utilisateurs $entity
     * @param string $newPassword
     */
    private function encodeUserPassword(Utilisateurs $entity, string $newPassword): void
    {
        $entity->setPassword($this->encoder->hashPassword($entity, $newPassword));
    }

    /**
     * @param string $title
     * @param string $action
     * @param object $entity
     * @param string $icon
     * @param string $color
     * @return void
     */
    private function sendNotif(string $title, string $action, object $entity, string $icon, string $color): void
    {
        $this->notification->save($title, $action, $entity, $icon, $color);
    }
}
