<?php

declare(strict_types=1);

namespace App\Module\ProjectManagement\Infrastructure\Mcp\Tool\Task;

use App\Module\ProjectManagement\Domain\Entity\TaskDocument;
use App\Module\ProjectManagement\Domain\Repository\TaskRepositoryInterface;
use DateTimeImmutable;
use Doctrine\ORM\EntityManagerInterface;
use InvalidArgumentException;
use Mcp\Capability\Attribute\McpTool;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Symfony\Component\Uid\Uuid;

use function sprintf;
use function strlen;

#[McpTool(name: 'add-task-document', description: 'Attach a text document (Markdown by default) to a task by passing its raw content. Optimized for Markdown reports/notes: the content is written verbatim as a UTF-8 file, no base64 needed. The MIME type is inferred from the fileName extension (.md, .txt, .csv, .json, .xml), defaulting to text/markdown.')]
class AddTaskDocumentTool
{
    private const MAX_CONTENT_SIZE = 5 * 1024 * 1024; // 5 MB of text

    private const EXTENSION_TO_MIME = [
        'md'       => 'text/markdown',
        'markdown' => 'text/markdown',
        'txt'      => 'text/plain',
        'csv'      => 'text/csv',
        'json'     => 'application/json',
        'xml'      => 'text/xml',
    ];

    public function __construct(
        private readonly EntityManagerInterface $entityManager,
        private readonly TaskRepositoryInterface $taskRepository,
        private readonly Security $security,
        private readonly string $uploadDir,
    ) {}

    /**
     * @param int    $taskId   ID of the task to attach the document to
     * @param string $content  Raw text content of the document (e.g. Markdown)
     * @param string $fileName Display name of the document, including extension (defaults to "document.md")
     */
    public function __invoke(
        int $taskId,
        string $content,
        string $fileName = 'document.md',
    ): string {
        if (!$this->security->isGranted('ROLE_USER')) {
            throw new AccessDeniedException('Access denied: ROLE_USER required.');
        }

        $task = $this->taskRepository->findById($taskId);
        if (null === $task) {
            throw new InvalidArgumentException(sprintf('Task with ID %d not found.', $taskId));
        }

        if ('' === $content) {
            throw new InvalidArgumentException('Document content cannot be empty.');
        }

        $size = strlen($content);
        if ($size > self::MAX_CONTENT_SIZE) {
            throw new InvalidArgumentException('Content size exceeds 5 MB limit.');
        }

        $originalName = '' !== trim($fileName) ? trim($fileName) : 'document.md';

        $extension = strtolower(pathinfo($originalName, PATHINFO_EXTENSION));
        $mimeType  = self::EXTENSION_TO_MIME[$extension] ?? 'text/markdown';
        if ('' === $extension) {
            $originalName .= '.md';
            $extension = 'md';
        }

        $storedName = Uuid::v4()->toRfc4122().'.'.$extension;

        if (!is_dir($this->uploadDir) && !mkdir($this->uploadDir, 0o775, true) && !is_dir($this->uploadDir)) {
            throw new InvalidArgumentException(sprintf('Upload directory "%s" could not be created.', $this->uploadDir));
        }

        if (false === file_put_contents($this->uploadDir.'/'.$storedName, $content)) {
            throw new InvalidArgumentException('Failed to write document to disk.');
        }

        $document = new TaskDocument();
        $document->setTask($task);
        $document->setOriginalName($originalName);
        $document->setFileName($storedName);
        $document->setMimeType($mimeType);
        $document->setSize($size);
        $document->setCreatedAt(new DateTimeImmutable());
        $document->setUploadedBy($this->security->getUser());

        $this->entityManager->persist($document);
        $this->entityManager->flush();

        return json_encode([
            'id'           => $document->getId(),
            'taskId'       => $task->getId(),
            'originalName' => $document->getOriginalName(),
            'mimeType'     => $document->getMimeType(),
            'size'         => $document->getSize(),
            'createdAt'    => $document->getCreatedAt()?->format('c'),
            'uploadedBy'   => $document->getUploadedBy()?->getUsername(),
        ]);
    }
}
