<?php

declare(strict_types=1);

namespace App\Framework\Reflection\Contracts;

use App\Framework\Core\ValueObjects\ClassName;

/**
 * Interface for instantiation-related reflection operations
 */
interface InstantiationReflector
{
    /**
     * Check if a class is instantiable
     *
     * @param ClassName $className The class name to check
     * @return bool True if the class is instantiable, false otherwise
     */
    public function isInstantiable(ClassName $className): bool;

    /**
     * Create a new instance of a class
     *
     * @param ClassName $className The class name to instantiate
     * @param array<mixed> $args Constructor arguments
     * @return object The new instance
     * @throws \ReflectionException If the class is not instantiable
     */
    public function createInstance(ClassName $className, array $args = []): object;

    /**
     * Create a new instance of a class without calling the constructor
     *
     * @param ClassName $className The class name to instantiate
     * @return object The new instance
     * @throws \ReflectionException If the class is not instantiable
     */
    public function createInstanceWithoutConstructor(ClassName $className): object;

    /**
     * Create a lazy ghost of a class (PHP 8.1+)
     *
     * @param ClassName $className The class name to create a lazy ghost for
     * @param callable $initializer The initializer function
     * @param int $options Optional options for lazy ghost creation
     * @return object The lazy ghost
     * @throws \ReflectionException If the class is not instantiable or lazy ghosts are not supported
     */
    public function createLazyGhost(ClassName $className, callable $initializer, int $options = 0): object;

    /**
     * Create a lazy proxy of a class (PHP 8.1+)
     *
     * @param ClassName $className The class name to create a lazy proxy for
     * @param callable $factory The factory function
     * @param int $options Optional options for lazy proxy creation
     * @return object The lazy proxy
     * @throws \ReflectionException If the class is not instantiable or lazy proxies are not supported
     */
    public function createLazyProxy(ClassName $className, callable $factory, int $options = 0): object;

    /**
     * Check if a class has a constructor
     *
     * @param ClassName $className The class name to check
     * @return bool True if the class has a constructor, false otherwise
     */
    public function hasConstructor(ClassName $className): bool;

    /**
     * Get constructor parameters
     *
     * @param ClassName $className The class name to get constructor parameters for
     * @return array<\ReflectionParameter> Array of constructor parameters
     */
    public function getConstructorParameters(ClassName $className): array;

    /**
     * Check if a class is abstract
     *
     * @param ClassName $className The class name to check
     * @return bool True if the class is abstract, false otherwise
     */
    public function isAbstract(ClassName $className): bool;

    /**
     * Check if a class is final
     *
     * @param ClassName $className The class name to check
     * @return bool True if the class is final, false otherwise
     */
    public function isFinal(ClassName $className): bool;

    /**
     * Check if a class is internal
     *
     * @param ClassName $className The class name to check
     * @return bool True if the class is internal, false otherwise
     */
    public function isInternal(ClassName $className): bool;

    /**
     * Check if a class is user-defined
     *
     * @param ClassName $className The class name to check
     * @return bool True if the class is user-defined, false otherwise
     */
    public function isUserDefined(ClassName $className): bool;
}
