<?php

namespace App\Controller;

use App\Entity\Capsule;
use App\Entity\Group;
use App\Entity\User;
use App\Form\DeleteCapsuleFormType;
use App\Form\DuplicateCapsuleFormType;
use App\Form\FilterByGroupFormType;
use App\Helper\StringHelper;
use App\Repository\CapsuleRepository;
use App\Builder\CapsuleBuilder;
use App\Form\CreateCapsuleFormType;
use Knp\Component\Pager\PaginatorInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Uid\Uuid;
use Symfony\Contracts\Translation\TranslatorInterface;

class CapsuleController extends AbstractController
{
    private CapsuleRepository $capsule_repository;
    private TranslatorInterface $translator;

    public function __construct(
        CapsuleRepository $capsule_repository,
        TranslatorInterface $translator
    ) {
        $this->capsule_repository = $capsule_repository;
        $this->translator = $translator;
    }

    /**
     * @Route("/my_capsules", name="capsule_list")
     * @Route("/", name="home")
     */
    public function index(
        PaginatorInterface $paginator,
        Request $request
    ): Response {
        $current_user = $this->getUser();

        if (! $current_user instanceof User) {
            return $this->redirectToRoute('app_logout');
        }

        $all_capsules = $current_user->getCapsules();

        $form = $this->createForm(FilterByGroupFormType::class, ['groups' => $current_user->getGroups()]);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $group = $form->getData()['name'];

            if (! $group instanceof Group) {
                throw new \Exception('Group not found');
            }

            $all_capsules = $current_user->getCapsulesFilteredByGroup($group);
        }

        $capsules = $paginator->paginate(
            $all_capsules,
            $request->query->getInt('page', 1),
            5
        );

        return $this->render('capsule/index.html.twig', [
            'filterByGroupForm' => $form->createView(),
            'capsules' => $capsules,
            'current_user' => $current_user,
            'legacy_url' => $this->getParameter('app.legacy_external_prefix')
        ]);
    }

    /**
     * @Route("/create", name="create_capsule")
     */
    public function create(Request $request): Response
    {
        $form = $this->createForm(CreateCapsuleFormType::class);
        $form->handleRequest($request);
        $current_user = $this->getUser();

        if (! $current_user instanceof User) {
            return $this->redirectToRoute('app_logout');
        }

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

            $capsule = $this->createCapsuleInDB($form, $current_user);

            return $this->forward('App\Controller\ProjectController::create', [
                'capsule' => $capsule,
                'video_url' => $video_url
            ]);
        }

        return $this->render('capsule/create.html.twig', [
            'capsuleCreationForm' => $form->createView()
            ]);
    }

    /**
     * @Route("capsule/preview/{path}", name="preview_capsule")
     */
    public function preview(string $path): Response
    {
        $file_path = '../legacy/' . $path;
        if (!file_exists($file_path)) {
            return $this->render('project/project_not_found.html.twig');
        }

        $url = $this->getParameter('app.legacy_external_prefix') . '/' . $path . "/?w=1";

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

    /**
     * @Route("capsule/edit/{path}", name="edit_capsule")
     */
    public function edit(string $path): Response
    {
        $current_user = $this->getUser();

        if (! $current_user instanceof User) {
            return $this->redirectToRoute('app_logout');
        }

        $capsule = $this->capsule_repository->findOneBy(['link_path' => $path]);
        if (null === $capsule) {
            $this->addFlash('warning', $this->translator->trans('capsule.edit.not_found'));
            return $this->redirectToRoute('capsule_list');
        }

        if (! $capsule->getEditors()->contains($current_user)) {
            $this->addFlash('warning', $this->translator->trans('capsule.edit.not_allowed'));
            return $this->redirectToRoute('capsule_list');
        }

        $file_path = '../legacy/' . $path;
        if (!file_exists($file_path)) {
            return $this->render('project/project_not_found.html.twig');
        }

        $url = $this->getParameter('app.legacy_external_prefix') . '/' . $capsule->getEditionLink();

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

    /**
     * @Route("/capsule/delete/{id}", name="delete_capsule")
     */
    public function delete(
        int $id,
        Request $request
    ): Response {
        $form = $this->createForm(DeleteCapsuleFormType::class);
        $form->handleRequest($request);
        $current_user = $this->getUser();

        if (! $current_user instanceof User) {
            return $this->redirectToRoute('app_logout');
        }

        $entityManager = $this->getDoctrine()->getManager();
        $capsule = $entityManager->getRepository(Capsule::class)->find($id);

        if (! $capsule) {
            throw $this->createNotFoundException(
                'No capsule found for id ' . $id
            );
        }
        $capsule_name = $capsule->getName();

        if ($capsule->getCreationAuthor() !== $current_user) {
            $this->addFlash(
                'warning',
                $this->translator->trans(
                    'capsule.delete.error',
                    [
                        'capsule_name' => $capsule_name
                    ]
                )
            );

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

        if ($form->isSubmitted() && $form->isValid()) {
            $current_user->removeCapsule($capsule);
            $capsule->removeEditor($current_user);
            $entityManager->remove($capsule);
            $entityManager->flush();

            $this->addFlash(
                'success',
                $this->translator->trans(
                    'capsule.delete.success',
                    [
                        'capsule_name' => $capsule_name
                    ]
                )
            );

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

        return $this->render('capsule/delete.html.twig', [
            'deleteCapsuleForm' => $form->createView(),
            'capsule_name' => $capsule_name
        ]);
    }

    /**
     * @Route("/capsule/duplicate/{id}", name="duplicate_capsule")
     */
    public function duplicate(
        int $id,
        Request $request,
        Filesystem $file_system
    ): Response {
        $form = $this->createForm(DuplicateCapsuleFormType::class);
        $form->handleRequest($request);
        $current_user = $this->getUser();

        if (! $current_user instanceof User) {
            return $this->redirectToRoute('app_logout');
        }

        $entityManager = $this->getDoctrine()->getManager();
        $parent_capsule = $entityManager->getRepository(Capsule::class)->find($id);

        if (! $parent_capsule instanceof Capsule) {
            throw new \Exception('The retrieved capsule is not an instance of Capsule.');
        }

        $capsule_editors = $parent_capsule->getEditors();

        if (! in_array($current_user, $capsule_editors->toArray())) {
            $this->addFlash(
                'warning',
                $this->translator->trans(
                    'capsule.duplicate.error',
                    [
                        'capsule_name' => $parent_capsule->getName()
                    ]
                )
            );

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

        $parent_directory_name = $parent_capsule->getLinkPath();
        $parent_directory_exists = $file_system->exists('../legacy/' . $parent_directory_name);
        if (! $parent_directory_exists) {
            $this->addFlash(
                'warning',
                $this->translator->trans(
                    'project.not_exist',
                    [
                        'capsule_name' => $parent_capsule->getName()
                    ]
                )
            );

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

        if ($form->isSubmitted() && $form->isValid()) {
            $capsule = $this->createCapsuleInDB($form, $current_user);

            return $this->forward('App\Controller\ProjectController::duplicate', [
                'capsule' => $capsule,
                'parent_directory' => $parent_directory_name
            ]);
        }

        return $this->render('capsule/duplicate.html.twig', [
            'duplicateCapsuleForm' => $form->createView(),
            'capsule_name' => $parent_capsule->getName()
        ]);
    }

    private function createCapsuleInDB(FormInterface $form, User $current_user): Capsule
    {
        $new_date_time = new \DateTime();
        $capsule_name = $form->get('name')->getData();
        $password = StringHelper::generateRandomHashedString();
        $preview_link = Uuid::v4();

        $entityManager = $this->getDoctrine()->getManager();
        $capsule_builder = new CapsuleBuilder();
        $capsule = $capsule_builder
            ->withName($capsule_name)
            ->withCreationAuthor($current_user)
            ->withCreationDate($new_date_time)
            ->withLinkPath($preview_link)
            ->withUpdateDate($new_date_time)
            ->withPassword($password)
            ->createCapsule();

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

        return $capsule;
    }
}