<?php
declare(strict_types=1);

namespace App\Framework\Validation;

use ReflectionClass;

final class Validator
{
    /**
     * Validiert ein Objekt und gibt das Ergebnis zurück
     *
     * @param object $object Das zu validierende Objekt
     * @param string|null $group Optionale Validierungsgruppe
     * @return ValidationResult
     */
    public function validate(object $object, ?string $group = null): ValidationResult
    {
        $result = new ValidationResult();
        $refClass = new ReflectionClass($object);

        // Eigenschaften validieren
        foreach ($refClass->getProperties() as $property) {

            try {

                if(!$property?->isInitialized($object) && !$property->getType()?->allowsNull()){

                    $result->addError(
                        $property->getName(),
                        sprintf("Feld '%s' darf nicht null sein.", $property->getName())
                    );

                    continue;
                }


                $value = $property->getValue($object);
            } catch (\Throwable) {

                //$result->addError($property->getName(), 'Fehler beim Lesen des Werts');
                continue;
            }


            foreach ($property->getAttributes() as $attribute) {
                $attrInstance = $attribute->newInstance();


                if ($attrInstance instanceof ValidationRule) {
                    $shouldValidate = false;

                    if ($group === null) {
                        $shouldValidate = true;
                    } elseif ($attrInstance instanceof GroupAware) {
                        $shouldValidate = $attrInstance->belongsToGroup($group);
                    } else {
                        $shouldValidate = true;
                    }

                    if ($shouldValidate && !$attrInstance->validate($value)) {
                        $result->addErrors($property->getName(), $attrInstance->getErrorMessages());
                    }
                }
            }

        }

        return $result;
    }
}
