<?php

namespace App\Controller;

use App\Entity\Comment;
use App\Entity\Project;
use App\Entity\Task;
use App\Form\CsvType;
use App\Form\ProjectType;
use App\Service\OverpassClient;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted;
use Symfony\Contracts\Translation\TranslatorInterface;

#[Route('/project')]
class ProjectController extends AbstractController
{
    // Page des projets, où l'on voit tous les projets
    #[Route('/', name: 'app_project')]
    public function index(EntityManagerInterface $entityManager): Response
    {
        $projects = $entityManager->getRepository(Project::class)->findAllOrderedByActivity();

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

    // Formulaire de création d’un projet
    #[Route('/create', name: 'app_project_create')]
    #[IsGranted('ROLE_USER')]
    public function create(Request $request, EntityManagerInterface $entityManager, TranslatorInterface $translator): Response
    {
        $project = new Project();
        $createForm = $this->createForm(ProjectType::class, $project);
        $createForm->add('submit', SubmitType::class, [
            'label' => 'button.create_project',
        ]);

        $createForm->handleRequest($request);
        if ($createForm->isSubmitted() and $createForm->isValid()) {
            $project = $createForm->getData();

            try {
                $project->setCreatedBy($this->getUser());
                $entityManager->persist($project);
                $entityManager->flush();

                $this->addFlash('success', $translator->trans('alert.project_created'));

                return $this->redirectToRoute('app_project');
            } catch (\Exception $exception) {
                $this->addFlash('danger', $translator->trans('alert.project_not_created'));
            }
        }

        return $this->render('project/create.html.twig', [
            'create_form' => $createForm,
        ]);
    }

    // Page d’un prtojet donné (où l’on voit ses tâches)
    #[Route('/{slug}', name: 'app_project_show')]
    public function show(EntityManagerInterface $entityManager, TranslatorInterface $translator, $slug): Response
    {
        $project = $entityManager->getRepository(Project::class)->findOneBySlug($slug);
        if (!$project) {
            $this->addFlash('warning', $translator->trans('alert.project_not_found'));

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

        $tasks = $entityManager->getRepository(Task::class)->findByProjectPaginated($project);
        $randomTask = $entityManager->getRepository(Task::class)->findRandomByProject($project, Task::STATUS_TODO); // Trouve la tâche à faire que l’on piochera

        $csvForm = $this->createForm(CsvType::class, null, [
            'action' => $this->generateUrl('app_project_import', ['slug' => $slug]),
        ]);
        $csvForm->add('submit', SubmitType::class, [
            'label' => 'button.import',
        ]);

        $comments = $entityManager->getRepository(Comment::class)->findLatestByProject($project); // Commentaires agrégés de toutes les tâches du projet

        return $this->render('project/show.html.twig', [
            'project' => $project,
            'tasks' => $tasks,
            'csv_form' => $csvForm,
            'comments' => $comments,
            'randomTask' => $randomTask,
        ]);
    }

    // Import de tâches dans un projet
    #[Route('/{slug}/import', name: 'app_project_import')]
    #[IsGranted('ROLE_USER')]
    public function import(Request $request, EntityManagerInterface $entityManager, TranslatorInterface $translator, $slug): Response
    {
        $project = $entityManager->getRepository(Project::class)->findOneBySlug($slug);
        if (!$project) {
            $this->addFlash('warning', $translator->trans('alert.project_not_found'));

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

        $csvForm = $this->createForm(CsvType::class, null, [
            'allow_extra_fields' => true,
        ]);
        $csvForm->handleRequest($request);
        if ($csvForm->isSubmitted() and $csvForm->isValid()) {
            $csvFile = $csvForm->get('csv')->getData();

            // TODO un peu plus de gestion d’erreur ici serait pas du luxe…
            $csv = fopen($csvFile->getPathName(), 'r');
            $col = array_flip(fgetcsv($csv));
            while ($row = fgetcsv($csv)) {
                $task = new Task();
                $task->setCreatedBy($this->getUser());
                $task->setProject($project);
                $task->setName($row[$col['name']]);
                $task->setDescription($row[$col['description']]);
                $task->setOsm($row[$col['osm']]);
                $task->setGeojson($row[$col['geojson']]);
                if (isset($row[$col['status']]) and in_array($row[$col['status']], [
                    Task::STATUS_TODO,
                    Task::STATUS_DOING,
                    Task::STATUS_DONE,
                ])) {
                    $task->setStatus($row[$col['status']]);
                } else {
                    $task->setStatus(Task::STATUS_TODO);
                }
                $entityManager->persist($task);
            }
            $entityManager->flush();
        }

        return $this->redirectToRoute('app_project_show', ['slug' => $slug]);
    }

    // Page de modification du projet
    #[Route('/{slug}/update', name: 'app_project_update')]
    #[IsGranted('ROLE_USER')]
    public function update(Request $request, EntityManagerInterface $entityManager, TranslatorInterface $translator, $slug): Response
    {
        $repository = $entityManager->getRepository(Project::class);
        $project = $repository->findOneBySlug($slug);

        if (!$project) {
            $this->addFlash('warning', $translator->trans('alert.project_not_found'));

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

        $updateForm = $this->createForm(ProjectType::class, $project);
        $updateForm->add('submit', SubmitType::class, [
            'label' => 'button.update_project',
        ]);

        $updateForm->handleRequest($request);
        if ($updateForm->isSubmitted() and $updateForm->isValid()) {
            $project = $updateForm->getData();

            try {
                $entityManager->persist($project);
                $entityManager->flush();

                $this->addFlash('success', $translator->trans('alert.project_updated'));

                return $this->redirectToRoute('app_project_show', ['slug' => $slug]);
            } catch (\Exception $exception) {
                $this->addFlash('danger', $translator->trans('alert.project_not_updated'));
            }
        }

        return $this->render('project/update.html.twig', [
            'project' => $project,
            'update_form' => $updateForm,
        ]);
    }

    // La suppression d’un projet passe par là
    #[Route('/{slug}/remove', name: 'app_project_remove')]
    #[IsGranted('ROLE_USER')]
    public function remove(EntityManagerInterface $entityManager, TranslatorInterface $translator, $slug): Response
    {
        $repository = $entityManager->getRepository(Project::class);
        $project = $repository->findOneBySlug($slug);

        if (!$project) {
            $this->addFlash('warning', $translator->trans('alert.project_not_found'));

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

        try {
            $entityManager->remove($project);
            $entityManager->flush();

            $this->addFlash('success', $translator->trans('alert.project_removed'));

            return $this->redirectToRoute('app_project');
        } catch (\Exception $exception) {
            $this->addFlash('danger', $translator->trans('alert.project_not_removed'));
        }

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

    // Effectue la requête Overpass liée au projet
    #[Route('/{slug}/overpass', name: 'app_project_overpass')]
    #[IsGranted('ROLE_USER')]
    public function overpass(OverpassClient $overpassClient, EntityManagerInterface $entityManager, TranslatorInterface $translator, $slug): Response
    {
        $repository = $entityManager->getRepository(Project::class);
        $project = $repository->findOneBySlug($slug);

        if (!$project) {
            $this->addFlash('warning', $translator->trans('alert.project_not_found'));

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

        if (!$project->hasOverpassQuery()) {
            $this->addFlash('warning', $translator->trans('alert.no_overpass_query'));

            return $this->redirectToRoute('app_project_show', ['slug' => $project->getSlug()]);
        }

        if ($project->hasOverpassResult() and !$project->isOverpassResultOutdated()) {
            $this->addFlash('warning', $translator->trans('alert.overpass_please_wait'));

            return $this->redirectToRoute('app_project_show', ['slug' => $project->getSlug()]);
        }

        $result = $overpassClient->query($project->getOverpassQuery());

        $project->setOverpassResult($result);

        $entityManager->persist($project);
        $entityManager->flush();

        return $this->redirectToRoute('app_project_show', ['slug' => $project->getSlug()]);
    }
}
