<?php

declare(strict_types=1);

namespace App\Framework\Router;

use App\Framework\Core\ValueObjects\ClassName;
use App\Framework\DI\DefaultContainer;
use App\Framework\Http\RequestBody;
use App\Framework\Reflection\ReflectionProvider;
use App\Framework\Reflection\WrappedReflectionClass;
use App\Framework\Validation\Exceptions\ValidationException;
use App\Framework\Validation\Validator;

final readonly class ControllerRequestFactory
{
    public function __construct(
        private DefaultContainer       $container,
        private PropertyValueConverter $propertyValueConverter,
        private ReflectionProvider     $reflectionProvider
    ) {
    }

    /**
     * Erstellt und validiert eine ControllerRequest-Instanz
     */
    public function createAndValidate(WrappedReflectionClass $requestClass, RequestBody $data): object
    {
        // Native ReflectionClass für Instanziierung holen
        $className = ClassName::create($requestClass->getName());

        $class = $this->reflectionProvider->getClass($className);

        // Erst die Instanz erstellen
        $instance = $class->newInstance();

        $properties = $requestClass->getProperties();

        foreach ($properties as $property) {
            $propertyName = $property->getName();

            $value = $data->get($propertyName, null);

            try {
                // Jetzt auf die tatsächliche Instanz setzen
                $this->propertyValueConverter->setPropertyValue($property, $instance, $value);
            } catch (\Throwable $e) {
                // Fehler beim Setzen ignorieren
            }
        }

        $validator = $this->container->get(Validator::class);

        $validationResult = $validator->validate($instance);

        if ($validationResult->hasErrors()) {
            throw new ValidationException($validationResult, 'test');
        }

        return $instance;
    }
}
