<?php

declare(strict_types=1);

namespace App\Module\Mail\Infrastructure\Controller;

use App\Module\Mail\Domain\Entity\TaskMailLink;
use App\Module\Mail\Domain\Repository\MailMessageRepositoryInterface;
use App\Module\Mail\Domain\Repository\TaskMailLinkRepositoryInterface;
use App\Module\Mail\Infrastructure\Security\MailAccessChecker;
use App\Module\ProjectManagement\Domain\Repository\TaskRepositoryInterface;
use DateTimeImmutable;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpKernel\Exception\UnprocessableEntityHttpException;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted;

#[Route('/api/mail/messages/{id}/link-task', name: 'mail_link_task', methods: ['POST'], priority: 1, requirements: ['id' => '\d+'])]
#[IsGranted('IS_AUTHENTICATED_FULLY')]
class MailLinkTaskController extends AbstractController
{
    public function __construct(
        private readonly MailMessageRepositoryInterface $messageRepository,
        private readonly TaskMailLinkRepositoryInterface $linkRepository,
        private readonly TaskRepositoryInterface $taskRepository,
        private readonly EntityManagerInterface $em,
        private readonly MailAccessChecker $accessChecker,
    ) {}

    public function __invoke(Request $request, int $id): JsonResponse
    {
        $this->accessChecker->ensureCanAccessMail($this->getUser());

        $message = $this->messageRepository->findById($id);
        if (null === $message) {
            throw new NotFoundHttpException('Message not found');
        }

        $body   = json_decode($request->getContent(), true);
        $taskId = $body['taskId'] ?? null;

        if (null === $taskId) {
            throw new UnprocessableEntityHttpException('taskId is required');
        }

        $task = $this->taskRepository->findById((int) $taskId);
        if (null === $task) {
            throw new NotFoundHttpException('Task not found');
        }

        $existing = $this->linkRepository->findByTaskAndMessage($task, $message);
        if (null !== $existing) {
            return $this->json(['message' => 'Already linked']);
        }

        $link = new TaskMailLink();
        $link->setTask($task);
        $link->setMailMessage($message);
        $link->setLinkedAt(new DateTimeImmutable());
        $link->setLinkedBy($this->getUser());
        $this->em->persist($link);
        $this->em->flush();

        return $this->json(['linkId' => $link->getId(), 'taskId' => $task->getId(), 'messageId' => $message->getId()], 201);
    }
}
