<?php

namespace App\Infrastructure\Http;

use Exception;
use ReflectionClass;
use RuntimeException;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Controller\ValueResolverInterface;
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
use Symfony\Component\Serializer\SerializerInterface;
use Symfony\Component\Validator\Validator\ValidatorInterface;

class RequestDtoResolver implements ValueResolverInterface
{
    public function __construct(
        private readonly SerializerInterface $serializer,
        private readonly ValidatorInterface $validator
    ) {
    }

    public function supports(Request $request, ArgumentMetadata $argument): bool
    {
        $type = $argument->getType();

        if (empty($type) || !class_exists($type)) {
            return false;
        }

        try {
            $reflection = new ReflectionClass($type);
        } catch (Exception $e) {
            return false;
        }

        return $reflection->implementsInterface(RequestDtoInterface::class);
    }

    public function resolve(Request $request, ArgumentMetadata $argument): iterable
    {
        if (($class = $argument->getType()) === null || !class_exists($class)) {
            throw new RuntimeException('dto exception');
        }

        $object = $this->serializer->deserialize($request->getContent(), $class, 'json');

        if (is_object($object)) {
            $this->validateObject($object);
        }

        yield $object;
    }

    private function validateObject(object $object): void
    {
        $errors = $this->validator->validate($object);

        if (count($errors) > 0) {
            /* todo получать из вне сообщение для ошибки */
            throw new RuntimeException($errors, 'Ошибка валидации');
        }
    }
}
