<?php

declare(strict_types=1);

namespace App\Framework\Reflection;

use ReflectionClass;
use ReflectionAttribute;

final readonly class WrappedReflectionClass
{
    public function __construct(
        public ReflectionClass $reflection
    ) {}

    public function getName(): string
    {
        return $this->reflection->getName();
    }

    public function getShortName(): string
    {
        return $this->reflection->getShortName();
    }

    public function isInstantiable(): bool
    {
        return $this->reflection->isInstantiable();
    }

    public function implementsInterface(string $interface): bool
    {
        return $this->reflection->implementsInterface($interface);
    }

    // Erweiterte Convenience-Methoden
    public function getAttributeInstances(?string $attributeClass = null): array
    {
        $attributes = $this->reflection->getAttributes($attributeClass);
        return array_map(fn(ReflectionAttribute $attr) => $attr->newInstance(), $attributes);
    }

    public function hasAttribute(string $attributeClass): bool
    {
        return !empty($this->reflection->getAttributes($attributeClass));
    }

    public function getFirstAttribute(string $attributeClass): ?object
    {
        $instances = $this->getAttributeInstances($attributeClass);
        return $instances[0] ?? null;
    }

    public function getMethodsWithAttribute(string $attributeClass): array
    {
        $methods = [];
        foreach ($this->reflection->getMethods() as $method) {
            if (!empty($method->getAttributes($attributeClass))) {
                $methods[] = new WrappedReflectionMethod($method);
            }
        }
        return $methods;
    }

    public function getWrappedMethod(string $name): WrappedReflectionMethod
    {
        return new WrappedReflectionMethod($this->reflection->getMethod($name));
    }

    public function getWrappedMethods(?int $filter = null): array
    {
        return array_map(
            fn($method) => new WrappedReflectionMethod($method),
            $this->reflection->getMethods($filter)
        );
    }
}
