<?php

declare(strict_types=1);

namespace App\State;

use ApiPlatform\Metadata\Operation;
use ApiPlatform\State\ProcessorInterface;
use App\Entity\MileageAllowance;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\Uid\Uuid;

final readonly class MileageAllowanceAmountReceiptUploadProcessor implements ProcessorInterface
{
    public function __construct(
        private EntityManagerInterface $entityManager,
        private RequestStack $requestStack,
        #[Autowire('%kernel.project_dir%/var/uploads')]
        private string $uploadDir,
    ) {}

    public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = []): JsonResponse
    {
        if (!$data instanceof MileageAllowance) {
            throw new BadRequestHttpException('Invalid entity.');
        }

        $request = $this->requestStack->getCurrentRequest();
        $file    = $request?->files->get('file');

        if (null === $file) {
            throw new BadRequestHttpException('No file uploaded.');
        }

        if ('application/pdf' !== $file->getMimeType()) {
            throw new BadRequestHttpException('Only PDF files are accepted.');
        }

        $month        = $data->getMonth();
        $year         = $month?->format('Y') ?? date('Y');
        $monthNumber  = $month?->format('m') ?? date('m');
        $relativePath = sprintf('mileage-receipts/%s/%s', $year, $monthNumber);
        $absoluteDir  = sprintf('%s/%s', $this->uploadDir, $relativePath);

        if (!is_dir($absoluteDir)) {
            mkdir($absoluteDir, 0o755, true);
        }

        $filename     = Uuid::v4()->toRfc4122().'.pdf';
        $fullRelative = sprintf('%s/%s', $relativePath, $filename);
        $originalName = $file->getClientOriginalName();

        $file->move($absoluteDir, $filename);

        $data->setAmountReceiptPath($fullRelative);
        $data->setAmountReceiptName($originalName);
        $this->entityManager->flush();

        return new JsonResponse(['path' => $fullRelative, 'name' => $originalName], Response::HTTP_OK);
    }
}
