<?php

namespace App\Controller;

use App\Entity\Constitue;
use App\Entity\Mod;
use App\Entity\Modpack;
use App\Entity\User;
use App\Form\Mod\ModType;
use App\Form\Modpack\ModpackType;
use App\Form\User\UserFormType;
use App\Service\UploaderService;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\File\UploadedFile;
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\Security\Http\Attribute\CurrentUser;

#[Route('/administration')]
final class AdministrationController extends AbstractController
{
    #[Route('', name: 'app_admin')]
    public function index(): Response
    {
        return $this->render('administration/index.html.twig', [

        ]);
    }

    /* Users */
    #[route('/users', name: 'app_admin_users')]
    public function admin_users(EntityManagerInterface $em): Response
    {
        $users = $em->getRepository(User::class)->findAll(array(), array('id' => 'ASC'));

        return $this->render('administration/users/index.html.twig', [
            'users' => $users,
        ]);
    }

    #[Route('/users/add', name: 'app_admin_users_add')]
    public function admin_users_add(Request $request, EntityManagerInterface $em, #[currentUser] User $currentUser, UserPasswordHasherInterface $passwordHasher): Response
    {
        $user = new User();
        $form = $this->createForm(UserFormType::class, $user);
        $form ->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $plainPassword = $form->get('password')->getData();

            if (empty($plainPassword)) {
                $plainPassword = $user->getPseudo();
            }

            $hashedPassword = $passwordHasher->hashPassword($user, $plainPassword);
            $user->setPassword($hashedPassword);

            $user->setCreator($currentUser);
            $user->addRole('ROLE_USER');
            $em->persist($user);
            $em->flush();

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

        if ($form->isSubmitted() && !$form->isValid()) {
            $errors = $form->getErrors(true);
            foreach ($errors as $error) {
                $this->addFlash('warning',$error->getMessage());
            }

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



        return $this->render('administration/users/edit.html.twig', [
            'form' => $form->createView(),
        ]);
    }

    #[route('/users/{iduser}', name: 'app_admin_users_edit')]
    public function admin_users_edit(Request $request, EntityManagerInterface $em,#[currentUser] User $currentUser,UserPasswordHasherInterface $passwordHasher, int $iduser): Response
    {
        $user = $em->getRepository(User::class)->find($iduser);
        if (!$user) {
            $this->addFlash('warning', 'Utilisateur non trouvé.');
            return $this->redirectToRoute('app_admin_users');
        }

        if (!$currentUser->isAncestorOf($user)) {
            $this->addFlash('danger', 'Vous n\'avez pas la permission de modifier cet utilisateur.');
            return $this->redirectToRoute('app_admin_users');
        }

        $old_pwd = $user->getPseudo();

        $form = $this->createForm(UserFormType::class, $user);
        $form ->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $plainPassword = $form->get('password')->getData();

            if (empty($plainPassword)) {
                $plainPassword = $old_pwd;
            }
            else{
                $hashedPassword = $passwordHasher->hashPassword($user, $plainPassword);
                $user->setPassword($hashedPassword);
            }

            $this->addFlash('success', 'Utilisateur modifié avec succès.');

            $em->persist($user);
            $em->flush();

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

        if ($form->isSubmitted() && !$form->isValid()) {
            $errors = $form->getErrors(true);
            foreach ($errors as $error) {
                $this->addFlash('warning',$error->getMessage());
            }

            return $this->redirectToRoute('app_admin_users_edit', ['iduser' => $user->getId()]);
        }

        return $this->render('administration/users/edit.html.twig', [
            'form' => $form->createView(),
        ]);
    }

    /* Mods & Modpack*/
    #[Route('/mods', name: 'app_admin_mods')]
    public function admin_mods(EntityManagerInterface $em): Response
    {
        $mods = $em->getRepository(Mod::class)->findBy(array(), array('nom' => 'ASC','version' => 'ASC'));

        return $this->render('administration/mods/index.html.twig', [
            'mods' => $mods,
        ]);
    }

    #[Route('/mods/add', name: 'app_admin_mods_add')]
    public function admin_mods_add(Request $request, EntityManagerInterface $em, UploaderService $uploaderService): Response
    {
        $mod = new Mod();
        $form = $this->createForm(ModType::class, $mod);
        $form ->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            /** @var UploadedFile $photo */
            $filemod = $form->get('uri')->getData();
            if (!$filemod) {
                $this->addFlash('danger', 'Fichier du mod manquant.');
                return $this->redirectToRoute('app_admin_mods_add');
            }
            $filemodname = null;
            try {
                $filemodname = $uploaderService->upload($filemod, UploaderService::DIR_MOD,true);
            }
            catch (\Exception $exception){
                $this->addFlash('danger','Le mod est déjà enregistré.');
                return $this->redirectToRoute('app_admin_mods_add');
            }
            $mod->setUri($filemodname);

            $em->persist($mod);
            $em->flush();
            $this->addFlash('success', 'Mod ajouté avec succès.');
            return $this->redirectToRoute('app_admin_mods');
        }
        if ($form->isSubmitted() && !$form->isValid()) {
            $errors = $form->getErrors(true);
            foreach ($errors as $error) {
                $errorMessage = $error->getMessage();
                if ($errorMessage === 'Mod already exists'){
                    $this->addFlash('danger', 'Le mod existe déjà. Veuillez vérifier le nom et la version du mod que vous essayez d\'ajouter.');
                    return $this->redirectToRoute('app_admin_mods_add');
                }
                $this->addFlash('warning',$errorMessage);
            }
            return $this->redirectToRoute('app_admin_mods_add');
        }

        return $this->render('administration/mods/edit.html.twig', [
            'form' => $form->createView(),
        ]);
    }

        #[route('/mods/{idmod}', name: 'app_admin_mods_edit')]
        public function admin_mods_edit(Request $request, EntityManagerInterface $em, int $idmod): Response
        {
            $mod = $em->getRepository(Mod::class)->find($idmod);
            if (!$mod) {
                $this->addFlash('warning', 'Mod non trouvé.');
                return $this->redirectToRoute('app_admin_mods');
            }
            $form = $this->createForm(ModType::class,$mod);
            $form ->handleRequest($request);

            if ($form->isSubmitted() && $form->isValid()) {

                $em->persist($mod);
                try {
                    $em->flush();
                }
                catch (\Exception $exception){
                    $this->addFlash('danger', 'Le mod existe déjà. Veuillez vérifier la version du mod que vous essayez de modifier.');
                    return $this->redirectToRoute('app_admin_mods_edit', ['idmod' => $idmod]);
                }
                $this->addFlash('success', 'Mod modifié avec succès.');
                return $this->redirectToRoute('app_admin_mods');
            }

            return $this->render('administration/mods/edit.html.twig', [
                'form' => $form->createView(),
            ]);
        }

        #[route('/mods/{idmod}/delete', name: 'app_admin_mods_delete')]
        public function admin_mods_delete(Request $request, EntityManagerInterface $em, UploaderService $uploaderService,int $idmod): Response
        {
            $mod = $em->getRepository(Mod::class)->find($idmod);
            if (!$mod) {
                $this->addFlash('warning', 'Mod non trouvé.');
                return $this->redirectToRoute('app_admin_mods');
            }

            if($mod->isUsed()){
                $this->addFlash('danger', 'Impossible de supprimer le mod car il est utilisé dans un modpack. Veuillez d\'abord le retirer des modpacks qui l\'utilisent.');
                return $this->redirectToRoute('app_admin_mods');
            }

            if($mod->isADependance()){
                $this->addFlash('danger', 'Impossible de supprimer le mod car il est une dépendance d\'un autre mod. Veuillez d\'abord retirer cette dépendance des mods qui l\'utilisent.');
                return $this->redirectToRoute('app_admin_mods');
            }

            $res = $uploaderService->delete($mod->getUri(), UploaderService::DIR_MOD);
            if (empty($res)) {
                $this->addFlash('warning', 'Fichier du mod introuvable ou déjà supprimé. Le mod a été supprimé de la base de données.');
            }
            if (!$res) {
                $this->addFlash('danger', 'Impossible de supprimer le mod.');
                return $this->redirectToRoute('app_admin_mods');
            }
            $em->remove($mod);
            $em->flush();
            $this->addFlash('success', 'Mod supprimé avec succès.');

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

        #[Route('/modpacks', name: 'app_admin_modpacks')]
        public function admin_modpacks(EntityManagerInterface $em): Response
        {
            $modpacks = $em->getRepository(Modpack::class)->findBy(array(), array('version' => 'DESC'));

            return $this->render('administration/modpacks/index.html.twig', [
                'modpacks' => $modpacks,
            ]);
        }

        #[Route('/modpacks/add', name: 'app_admin_modpacks_add')]
        public function admin_modpacks_add(Request $request, EntityManagerInterface $em): Response{
            $modpack = new Modpack();
            $form = $this->createForm(ModpackType::class, $modpack);
            $form->handleRequest($request);

            if ($form->isSubmitted()) {
                $optionnelsMods = $form->get('mods_optionnels')->getData() ?? new ArrayCollection();

                foreach ($form->get('mods')->getData() as $mod) {
                    $c = new Constitue();
                    $c->setModpack($modpack);
                    $c->setMod($mod);
                    $c->setOptionnel($optionnelsMods->contains($mod));
                    $em->persist($c);
                }

                $em->persist($modpack);
                $em->flush();

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


            $this->addFlash('success', 'Modpack ajouté avec succès.');
            return $this->render('administration/modpacks/edit.html.twig', [
                'form' => $form->createView(),
            ]);

        }

    #[Route('/modpacks/{id}', name: 'app_admin_modpacks_edit')]
    public function admin_modpacks_edit(Request $request, EntityManagerInterface $em, int $id): Response
    {
        $modpack = $em->getRepository(Modpack::class)->find($id);
        if (!$modpack) {
            $this->addFlash('warning', 'Modpack non trouvé.');
            return $this->redirectToRoute('app_admin_modpacks');
        }

        $form = $this->createForm(ModpackType::class, $modpack);

        // Pré-remplissage des champs mapped:false
        $form->get('mods')->setData($modpack->getMods());
        $form->get('mods_optionnels')->setData(
            $modpack->getConstitues()
                ->filter(fn(Constitue $c) => $c->isOptionnel())
                ->map(fn(Constitue $c) => $c->getMod())
        );

        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $optionnelsMods = $form->get('mods_optionnels')->getData() ?? new ArrayCollection();
            $newMods        = $form->get('mods')->getData()->toArray();

            foreach ($modpack->getConstitues() as $constitue) {
                $mod = $constitue->getMod();

                if (!in_array($mod, $newMods, true)) {
                    // Mod retiré : suppression
                    $em->remove($constitue);
                } else {
                    // Mod conservé : mise à jour de l'optionnel si besoin
                    $isOptionnel = $optionnelsMods->contains($mod);
                    if ($constitue->isOptionnel() !== $isOptionnel) {
                        $constitue->setOptionnel($isOptionnel);
                    }
                    // On le retire de $newMods pour ne pas le recréer
                    $newMods = array_filter($newMods, fn($m) => $m !== $mod);
                }
            }

            // Mods restants dans $newMods : nouveaux à créer
            foreach ($newMods as $mod) {
                $c = new Constitue();
                $c->setModpack($modpack);
                $c->setMod($mod);
                $c->setOptionnel($optionnelsMods->contains($mod));
                $em->persist($c);
            }

            $em->persist($modpack);
            $em->flush();

            $this->addFlash('success', 'Modpack modifié avec succès.');
            return $this->redirectToRoute('app_admin_modpacks');
        }

        return $this->render('administration/modpacks/edit.html.twig', [
            'form' => $form->createView(),
        ]);
    }

    #[route('/modpacks/{id}/delete', name: 'app_admin_modpacks_delete')]
    public function admin_modpacks_delete(Request $request, EntityManagerInterface $em, UploaderService $uploaderService,int $id): Response
    {
        $modpack = $em->getRepository(Modpack::class)->find($id);
        if (!$modpack) {
            $this->addFlash('warning', 'Modpack non trouvé.');
            return $this->redirectToRoute('app_admin_modpacks');
        }

        if ($modpack->isDownloadable()) {
            $this->addFlash('warning', 'Veuillez retirer ce modpack des versions téléchargeables pour le supprimer.');
            return $this->redirectToRoute('app_admin_modpacks');
        }

        foreach ($modpack->getConstitues() as $constitue) {
            $em->remove($constitue);
        }

        $em->remove($modpack);
        $em->flush();
        $this->addFlash('success', 'Modpack supprimé avec succès.');

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

}
