<?php

declare(strict_types=1);

namespace App\Framework\Reflection\Contracts;

use App\Framework\Core\ValueObjects\ClassName;
use App\Framework\Reflection\Collections\ParameterCollection;

/**
 * Interface for parameter-related reflection operations
 */
interface ParameterReflector
{
    /**
     * Get parameters for a method
     *
     * @param ClassName $className The class name containing the method
     * @param string $methodName The method name to get parameters for
     * @return ParameterCollection Collection of parameters
     */
    public function getMethodParameters(ClassName $className, string $methodName): ParameterCollection;

    /**
     * Get a specific parameter for a method
     *
     * @param ClassName $className The class name containing the method
     * @param string $methodName The method name containing the parameter
     * @param string $parameterName The parameter name to get
     * @return \ReflectionParameter The parameter
     * @throws \ReflectionException If the parameter does not exist
     */
    public function getMethodParameter(ClassName $className, string $methodName, string $parameterName): \ReflectionParameter;

    /**
     * Check if a method has a specific parameter
     *
     * @param ClassName $className The class name containing the method
     * @param string $methodName The method name to check
     * @param string $parameterName The parameter name to check for
     * @return bool True if the method has the parameter, false otherwise
     */
    public function hasMethodParameter(ClassName $className, string $methodName, string $parameterName): bool;

    /**
     * Get parameter type
     *
     * @param ClassName $className The class name containing the method
     * @param string $methodName The method name containing the parameter
     * @param string $parameterName The parameter name to get the type for
     * @return \ReflectionType|null The parameter type, or null if not typed
     */
    public function getParameterType(ClassName $className, string $methodName, string $parameterName): ?\ReflectionType;

    /**
     * Get parameter default value
     *
     * @param ClassName $className The class name containing the method
     * @param string $methodName The method name containing the parameter
     * @param string $parameterName The parameter name to get the default value for
     * @return mixed The parameter default value, or null if not set
     */
    public function getParameterDefaultValue(ClassName $className, string $methodName, string $parameterName): mixed;

    /**
     * Check if parameter is optional
     *
     * @param ClassName $className The class name containing the method
     * @param string $methodName The method name containing the parameter
     * @param string $parameterName The parameter name to check
     * @return bool True if the parameter is optional, false otherwise
     */
    public function isParameterOptional(ClassName $className, string $methodName, string $parameterName): bool;

    /**
     * Check if parameter is variadic
     *
     * @param ClassName $className The class name containing the method
     * @param string $methodName The method name containing the parameter
     * @param string $parameterName The parameter name to check
     * @return bool True if the parameter is variadic, false otherwise
     */
    public function isParameterVariadic(ClassName $className, string $methodName, string $parameterName): bool;

    /**
     * Get parameter attributes
     *
     * @param ClassName $className The class name containing the method
     * @param string $methodName The method name containing the parameter
     * @param string $parameterName The parameter name to get attributes for
     * @param string|null $attributeClass Optional attribute class to filter by
     * @return array<\ReflectionAttribute<object>> Array of parameter attributes
     */
    public function getParameterAttributes(
        ClassName $className,
        string $methodName,
        string $parameterName,
        ?string $attributeClass = null
    ): array;

    /**
     * Get detailed parameter information
     *
     * @param ClassName $className The class name containing the method
     * @param string $methodName The method name to get parameter info for
     * @return array<array<string, mixed>> Array of parameter information
     */
    public function getParameterInfo(ClassName $className, string $methodName): array;
}
