<?php

declare(strict_types=1);

namespace App\Framework\Reflection;

use App\Framework\Core\ValueObjects\ClassName;
use App\Framework\Reflection\Cache\ParameterCache;
use App\Framework\Reflection\Collections\AttributeCollection;
use ReflectionType;

final readonly class WrappedReflectionParameter
{
    public function __construct(
        private ClassName $className,
        private string $methodName,
        private int $position,
        private ParameterCache $cache
    ) {
    }

    public function getName(): string
    {
        return $this->cache->getParameterName($this->className, $this->methodName, $this->position);
    }

    public function getTypeName(): ?string
    {
        return $this->cache->getParameterTypeName($this->className, $this->methodName, $this->position);
    }

    public function isBuiltin(): bool
    {
        return $this->cache->isParameterTypeBuiltin($this->className, $this->methodName, $this->position);
    }

    public function isOptional(): bool
    {
        return $this->cache->isParameterOptional($this->className, $this->methodName, $this->position);
    }

    public function hasDefaultValue(): bool
    {
        return $this->cache->parameterHasDefaultValue($this->className, $this->methodName, $this->position);
    }

    public function getDefaultValue(): mixed
    {
        return $this->cache->getParameterDefaultValue($this->className, $this->methodName, $this->position);
    }

    public function allowsNull(): bool
    {
        return $this->cache->parameterAllowsNull($this->className, $this->methodName, $this->position);
    }

    public function getPosition(): int
    {
        return $this->position;
    }

    public function getAttributes(): AttributeCollection
    {
        return $this->cache->getParameterAttributes($this->className, $this->methodName, $this->position);
    }

    /**
     * Get the parameter attribute names
     *
     * @return array<string>
     */
    public function getAttributeNames(): array
    {
        return $this->getAttributes()->getNames();
    }

    /**
     * Get the parameter type - delegates to native ReflectionParameter
     */
    public function getType(): ?ReflectionType
    {
        return $this->cache->getParameterType($this->className, $this->methodName, $this->position);
    }

    // Convenience-Methode für DI
    public function toArray(): array
    {
        return [
            'name' => $this->getName(),
            'type' => $this->getTypeName(),
            'isBuiltin' => $this->isBuiltin(),
            'allowsNull' => $this->allowsNull(),
            'isOptional' => $this->isOptional(),
            'hasDefaultValue' => $this->hasDefaultValue(),
            'default' => $this->getDefaultValue(),
            'position' => $this->getPosition(),
            'attributes' => $this->getAttributes()->toArray(),
        ];
    }
}
