<?php

namespace App\Controller\Dashboard;

use App\Entity\Account;
use App\Event\Object\EventAdminCreate;
use App\Event\Object\EventAdminDeleted;
use App\Form\AccountPasswordType;
use App\Form\AccountType;
use App\Logger\AppLogger;
use App\Repository\AccountLoginRegisterRepository;
use App\Repository\AccountRepository;
use App\Repository\AuditLogRepository;
use App\Service\Mailer\Mailer;
use Doctrine\ORM\EntityManagerInterface;
use Knp\Component\Pager\PaginatorInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
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\Attribute\Route;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Csrf\TokenGenerator\TokenGeneratorInterface;
use Symfony\Component\Uid\Uuid;

#[Route('/crm/administrateur')]
class AccountController extends AbstractController
{
    public function __construct(
        private readonly EntityManagerInterface $em,
        private readonly AppLogger $appLogger,
        private readonly Mailer $mailer,
        private readonly EventDispatcherInterface $eventDispatcher,
        private readonly TokenGeneratorInterface $tokenGenerator,
        private readonly UrlGeneratorInterface $urlGenerator
    ) {
    }

    #[Route('', name: 'app_crm_administrateur', options: ['sitemap' => false], methods: ['GET'])]
    public function index(AccountRepository $accountRepository): Response
    {
        $this->appLogger->record('VIEW', 'Consultation de la liste des Administrateurs');

        return $this->render('dashboard/administrateur.twig', [
            'admins' => $accountRepository->findAdmin(),
        ]);
    }

    #[Route('/add', name: 'app_crm_administrateur_add', options: ['sitemap' => false], methods: ['GET', 'POST'])]
    public function add(Request $request, UserPasswordHasherInterface $passwordHasher): Response
    {
        $account = new Account();
        $account->setIsFirstLogin(true)
            ->setIsActif(false)
            ->setUuid(Uuid::v4()->toRfc4122())
            ->setRoles(['ROLE_ADMIN']);

        $form = $this->createForm(AccountType::class, $account);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $tempPassword = bin2hex(random_bytes(20));
            $account->setPassword($passwordHasher->hashPassword($account, $tempPassword));

            $this->em->persist($account);
            $this->em->flush();

            $this->appLogger->record('CREATE', sprintf(
                "Création de l'Administrateur : %s %s (%s)",
                $account->getFirstName(), $account->getName(), $account->getEmail()
            ));

            $this->eventDispatcher->dispatch(new EventAdminCreate($account, $this->getUser()));
            $this->addFlash('success', "L'Administrateur {$account->getFirstName()} a été créé avec succès.");

            return $this->redirectToRoute('app_crm_administrateur');
        }

        return $this->render('dashboard/administrateur/add.twig', ['form' => $form->createView()]);
    }

    #[Route('/{id}', name: 'app_crm_administrateur_view', options: ['sitemap' => false], methods: ['GET', 'POST'])]
    public function view(
        ?Account $account,
        Request $request,
        PaginatorInterface $paginator,
        AccountLoginRegisterRepository $loginRepo,
        AuditLogRepository $auditRepo,
        UserPasswordHasherInterface $passwordHasher
    ): Response {
        if (!$account) {
            $this->addFlash('error', 'Administrateur introuvable.');
            return $this->redirectToRoute('app_crm_administrateur');
        }

        // 1. Vérification Sécurité ROOT
        if ($redirect = $this->checkRootProtection($account)) {
            return $redirect;
        }

        // 2. Gestion des Actions Rapides (Query Params)
        if ($action = $request->query->get('act')) {
            return match ($action) {
                'disable2fa' => $this->handleDisable2FA($account),
                'sendLink2faenable' => $this->handleInvite2FA($account),
                'updateStatut' => $this->handleUpdateStatus($account, $request->query->get('status') === 'true'),
                'updateRoles' => $this->handleUpdateRoles($account, $request),
                default => $this->redirectToRoute('app_crm_administrateur_view', ['id' => $account->getId()])
            };
        }

        // 3. Formulaire Mot de passe
        $passwordForm = $this->createForm(AccountPasswordType::class, $account);
        $passwordForm->handleRequest($request);

        if ($passwordForm->isSubmitted() && $passwordForm->isValid()) {
            $plainPassword = $passwordForm->get('password')->getData();
            $account->setPassword($passwordHasher->hashPassword($account, $plainPassword));
            $this->em->flush();

            $this->mailer->send(
                $account->getEmail(),
                "{$account->getName()} {$account->getFirstName()}",
                "[Intranet Ludikevent] - Modification de votre mot de passe",
                "mails/account/password-modify.twig",
                ['who' => $this->getUser(), 'account' => $account, 'password' => $plainPassword]
            );

            $this->appLogger->record('UPDATE_PASSWORD', "Mot de passe modifié pour l'admin {$account->getId()}");
            $this->addFlash('success', 'Le mot de passe a été mis à jour et envoyé à l\'utilisateur.');
            return $this->redirectToRoute('app_crm_administrateur_view', ['id' => $account->getId()]);
        }

        // 4. Formulaire Identité
        $form = $this->createForm(AccountType::class, $account);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $this->em->flush();
            $this->appLogger->record('UPDATE_IDENTITY', "Mise à jour identité : {$account->getFirstName()} {$account->getName()}");
            $this->addFlash('success', 'Informations personnelles mises à jour.');
            return $this->redirectToRoute('app_crm_administrateur_view', ['id' => $account->getId()]);
        }

        // 5. Affichage
        $this->appLogger->record('VIEW', "Consultation : {$account->getFirstName()} {$account->getName()}");

        return $this->render('dashboard/administrateur/view.twig', [
            'admin' => $account,
            'form' => $form->createView(),
            'passwordForm' => $passwordForm->createView(),
            'loginRegisters' => $paginator->paginate($loginRepo->findBy(['account' => $account], ['loginAt' => 'DESC']), $request->query->getInt('page', 1), 10),
            'auditLogs' => $paginator->paginate($auditRepo->findBy(['account' => $account], ['actionAt' => 'DESC']), $request->query->getInt('audit_page', 1), 10, ['pageParameterName' => 'audit_page'])
        ]);
    }

    #[Route('/delete/{id}', name: 'app_crm_administrateur_delete', options: ['sitemap' => false], methods: ['POST'])]
    public function delete(Account $account, Request $request): Response
    {
        if ($redirect = $this->checkRootProtection($account)) {
            return $redirect;
        }

        if ($this->isCsrfTokenValid('delete' . $account->getId(), $request->request->get('_token'))) {
            $name = "{$account->getFirstName()} {$account->getName()}";

            $this->eventDispatcher->dispatch(new EventAdminDeleted($account, $this->getUser()));

            $this->em->remove($account);
            $this->em->flush();

            $this->appLogger->record('DELETE', "Suppression définitive : $name");
            $this->addFlash('success', "L'Administrateur $name a été supprimé.");
        } else {
            $this->addFlash('error', 'Jeton de sécurité invalide.');
        }

        return $this->redirectToRoute('app_crm_administrateur');
    }

    // --- PRIVATE HELPERS ---

    private function handleDisable2FA(Account $account): RedirectResponse
    {
        if ($account->isGoogleAuthenticatorEnabled()) {
            $account->setGoogleAuthenticatorSecret(null);
            $this->em->flush();

            $this->mailer->send(
                $account->getEmail(),
                "{$account->getFirstName()} {$account->getName()}",
                "[Alerte Sécurité] Désactivation de votre double authentification",
                "mails/account/2fa-disable.twig",
                ['account' => $account, 'who' => $this->getUser()]
            );

            $this->appLogger->record('2FA_DISABLED', "2FA désactivée pour {$account->getId()}");
            $this->addFlash('warning', "La protection 2FA de {$account->getFirstName()} a été retirée.");
        }
        return $this->redirectToRoute('app_crm_administrateur_view', ['id' => $account->getId()]);
    }

    private function handleInvite2FA(Account $account): RedirectResponse
    {
        $account->setConfirmationTokenName($this->tokenGenerator->generateToken());
        $this->em->flush();

        $setupUrl = $this->urlGenerator->generate('app_2fa_setup_confirm', [
            'id' => $account->getId(),
            'token' => $account->getConfirmationToken()
        ], UrlGeneratorInterface::ABSOLUTE_URL);

        $this->mailer->send(
            $account->getEmail(),
            "{$account->getFirstName()} {$account->getName()}",
            "[Sécurité] Configuration de votre double authentification (2FA)",
            "mails/account/2fa-invite.twig",
            [
                'account' => $account,
                'setup_url' => $setupUrl,
                'who' => $this->getUser(),
                'expires_at' => (new \DateTime('+1 hour'))->format('H:i')
            ]
        );

        $this->appLogger->record('2FA_INVITE', "Invitation 2FA envoyée à {$account->getId()}");
        $this->addFlash('success', "Lien 2FA envoyé à {$account->getFirstName()}");

        return $this->redirectToRoute('app_crm_administrateur_view', ['id' => $account->getId()]);
    }

    private function handleUpdateStatus(Account $account, bool $newStatus): RedirectResponse
    {
        $account->setIsActif($newStatus);
        $this->em->flush();

        $this->mailer->send(
            $account->getEmail(),
            "{$account->getFirstName()} {$account->getName()}",
            $newStatus ? "[Intranet Ludikevent] - Activation de votre accès" : "[Intranet Ludikevent] - Suspension de votre accès",
            "mails/account/status-update.twig",
            ['who' => $this->getUser(), 'account' => $account, 'stats' => $newStatus]
        );

        $label = $newStatus ? 'activé' : 'désactivé';
        $this->appLogger->record('UPDATE_STATUS', "Compte $label pour l'admin {$account->getId()}");
        $this->addFlash('success', "Le compte de {$account->getFirstName()} a été $label.");

        return $this->redirectToRoute('app_crm_administrateur_view', ['id' => $account->getId()]);
    }

    private function handleUpdateRoles(Account $account, Request $request): RedirectResponse
    {
        if ($request->isMethod('POST')) {
            $submittedRoles = $request->request->all('roles');
            $mandatoryRoles = ['ROLE_USER', 'ROLE_ADMIN'];

            foreach ($mandatoryRoles as $role) {
                if (!in_array($role, $submittedRoles)) {
                    $submittedRoles[] = $role;
                }
            }

            if (in_array('ROLE_CLIENT_MAIN', $submittedRoles) && !$this->isGranted('ROLE_ROOT')) {
                $this->addFlash('error', 'Action non autorisée : Privilège ROOT requis.');
                return $this->redirectToRoute('app_crm_administrateur_view', ['id' => $account->getId()]);
            }

            $account->setRoles($submittedRoles);
            $this->em->flush();

            $this->appLogger->record('UPDATE_ROLES', "Mise à jour rôles admin {$account->getId()}");
            $this->addFlash('success', 'Permissions mises à jour.');
        }

        return $this->redirectToRoute('app_crm_administrateur_view', ['id' => $account->getId()]);
    }

    private function checkRootProtection(Account $account): ?RedirectResponse
    {
        if (in_array('ROLE_ROOT', $account->getRoles())) {
            $title = "Tentative d'accès non autorisée";
            $details = sprintf("Tentative de modification/suppression de l'Admin ROOT protégé : %s (ID: %d) par %s",
                $account->getEmail(), $account->getId(), $this->getUser()->getUserIdentifier()
            );

            $this->appLogger->record('SECURITY_ALERT', $details);
            $this->sendSecurityEmail($title, $details);
            $this->addFlash('error', 'Sécurité : Le compte est protégé');

            return $this->redirectToRoute('app_crm_administrateur');
        }
        return null;
    }

    private function sendSecurityEmail(string $message, string $content): void
    {
        $this->mailer->send(
            'notification@siteconseil.fr',
            "Notification Intranet Ludikevent",
            "[Intranet Ludikevent] - $message",
            "mails/notification/security_violation.twig",
            [
                'message' => $message,
                'content' => $content,
                'account' => $this->getUser() ? $this->getUser()->getUserIdentifier() : 'Système',
                'date' => new \DateTime(),
            ]
        );
    }
}
