<?php

declare(strict_types=1);

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

use ApiPlatform\Metadata\Post;
use App\Module\ProjectManagement\Domain\Entity\Project;
use App\Module\ProjectManagement\Infrastructure\ApiPlatform\State\SwitchProjectWorkflowProcessor;
use Doctrine\ORM\EntityManagerInterface;
use Mcp\Capability\Attribute\McpTool;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Throwable;

#[McpTool(
    name: 'switch-project-workflow',
    description: 'Switch a project to another workflow. mapping must cover every status currently used by the project\'s tasks: keys are source status IDs (string), values are target status IDs in the new workflow (int) or null to send tasks to backlog. Requires ROLE_ADMIN. Returns { migratedTaskCount }.',
)]
class SwitchProjectWorkflowTool
{
    public function __construct(
        private readonly SwitchProjectWorkflowProcessor $processor,
        private readonly EntityManagerInterface $entityManager,
        private readonly Security $security,
    ) {}

    /**
     * @param array<string, null|int> $mapping
     */
    public function __invoke(int $projectId, int $workflowId, array $mapping): string
    {
        if (!$this->security->isGranted('ROLE_ADMIN')) {
            throw new AccessDeniedException('Access denied: ROLE_ADMIN required.');
        }

        $project = $this->entityManager->find(Project::class, $projectId);
        if (!$project) {
            return json_encode(['error' => 'Project not found.']);
        }

        $fakeRequest = Request::create('', 'POST', [], [], [], [], json_encode([
            'workflowId' => $workflowId,
            'mapping'    => $mapping,
        ]));

        try {
            $result = $this->processor->process(
                $project,
                operation: new Post(name: 'switch_workflow'),
                uriVariables: ['id' => $projectId],
                context: ['request' => $fakeRequest],
            );
        } catch (Throwable $e) {
            return json_encode(['error' => $e->getMessage()]);
        }

        return json_encode([
            'migratedTaskCount' => $result->migratedTaskCount,
            'projectId'         => $result->projectId,
            'workflowId'        => $result->workflowId,
        ]);
    }
}
