<?php

namespace App\Framework\DI;

use ReflectionClass;
use ReflectionMethod;

/**
 * Cache für ReflectionClass-Instanzen
 */
final class ReflectionCache
{
    private array $classCache = [];
    private array $methodCache = [];

    private array $parameterCache = [];

    public function get(string $class): ReflectionClass
    {
        return $this->classCache[$class] ??= new ReflectionClass($class);
    }

    public function getMethod(string $class, string $method): ReflectionMethod
    {
        $key = "{$class}::{$method}";
        return $this->methodCache[$key] ??= $this->get($class)->getMethod($method);
    }

    public function getMethodParameters(string $class, string $method): array
    {
        $key = "{$class}::{$method}::params";
        return $this->parameterCache[$key] ??= $this->getMethod($class, $method)->getParameters();
    }

    public function forget(string $class): void
    {
        unset($this->classCache[$class]);

        // Alle Methods dieser Klasse aus dem Cache entfernen
        $this->methodCache = array_filter(
            $this->methodCache,
            fn($key) => !str_starts_with($key, $class . '::'),
            ARRAY_FILTER_USE_KEY
        );

        $this->parameterCache = array_filter(
            $this->parameterCache,
            fn($key) => !str_starts_with($key, $class . '::'),
            ARRAY_FILTER_USE_KEY
        );
    }

    public function forgetMethod(string $class, string $method): void
    {
        unset($this->methodCache["{$class}::{$method}"]);
    }

    public function flush(): void
    {
        $this->classCache = [];
        $this->methodCache = [];
        $this->parameterCache = [];
    }
}
