<?php

declare(strict_types=1);

namespace App\Module\Absence\Infrastructure\Mcp\Tool;

use App\Module\Absence\Domain\Enum\AbsenceStatus;
use App\Module\Absence\Domain\Enum\AbsenceType;
use App\Module\Absence\Domain\Repository\AbsenceRequestRepositoryInterface;
use App\Module\Core\Domain\Repository\UserRepositoryInterface;
use App\Shared\Infrastructure\Mcp\Serializer;
use DateTimeImmutable;
use InvalidArgumentException;
use Mcp\Capability\Attribute\McpTool;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;

use function sprintf;

#[McpTool(name: 'list-absence-requests', description: 'List absence requests. Optional filters: userId, status (pending, approved, rejected, cancelled), type (cp, mariage_pacs, conge_parental, deces, maladie), from/to (YYYY-MM-DD, overlap window). Without userId returns all employees.')]
class ListAbsenceRequestsTool
{
    public function __construct(
        private readonly AbsenceRequestRepositoryInterface $requestRepository,
        private readonly UserRepositoryInterface $userRepository,
        private readonly Security $security,
    ) {}

    public function __invoke(
        ?int $userId = null,
        ?string $status = null,
        ?string $type = null,
        ?string $from = null,
        ?string $to = null,
    ): string {
        if (!$this->security->isGranted('ROLE_USER')) {
            throw new AccessDeniedException('Access denied: ROLE_USER required.');
        }

        $user = null;
        if (null !== $userId) {
            $user = $this->userRepository->findById($userId)
                ?? throw new InvalidArgumentException(sprintf('User with ID %d not found.', $userId));
        }

        $statusEnum = null;
        if (null !== $status) {
            $statusEnum = AbsenceStatus::tryFrom($status)
                ?? throw new InvalidArgumentException(sprintf('Unknown status "%s".', $status));
        }

        $typeEnum = null;
        if (null !== $type) {
            $typeEnum = AbsenceType::tryFrom($type)
                ?? throw new InvalidArgumentException(sprintf('Unknown absence type "%s".', $type));
        }

        $requests = $this->requestRepository->findFiltered(
            $user,
            $statusEnum,
            $typeEnum,
            null !== $from ? new DateTimeImmutable($from) : null,
            null !== $to ? new DateTimeImmutable($to) : null,
        );

        return json_encode(array_map(Serializer::absenceRequest(...), $requests));
    }
}
