<?php

declare(strict_types=1);

namespace App\Framework\Discovery;

use App\Framework\Discovery\Results\AttributeRegistry;
use App\Framework\Discovery\Results\DiscoveryRegistry;
use App\Framework\Discovery\Results\InterfaceRegistry;
use App\Framework\Discovery\Results\TemplateRegistry;
use App\Framework\Discovery\ValueObjects\InterfaceMapping;
use App\Framework\Discovery\ValueObjects\TemplateMapping;

/**
 * Memory-efficient collector for discovery data using the new registry system
 * Accumulates data directly into specialized registries to prevent memory bloat
 */
final readonly class DiscoveryDataCollector
{
    private AttributeRegistry $attributeRegistry;

    private InterfaceRegistry $interfaceRegistry;

    private TemplateRegistry $templateRegistry;

    public function __construct()
    {
        $this->attributeRegistry = new AttributeRegistry();
        $this->interfaceRegistry = new InterfaceRegistry();
        $this->templateRegistry = new TemplateRegistry();
    }

    /**
     * Add attributes from a batch - streams directly to registry
     */
    public function addAttributes(array $attributes): void
    {
        foreach ($attributes as $attributeClass => $attributeInstances) {
            foreach ($attributeInstances as $instance) {
                $this->attributeRegistry->add($attributeClass, $instance);
            }
        }
    }

    /**
     * Add interface implementations from a batch - streams directly to registry
     */
    public function addInterfaceImplementations(array $implementations): void
    {
        foreach ($implementations as $interface => $classes) {
            foreach ($classes as $class) {
                #$interfaceMapping = InterfaceMapping::create($interface, $class);
                $this->interfaceRegistry->add($interface, $class);
            }
        }
    }

    /**
     * Add routes from a batch - routes are now stored as Route attributes
     * @deprecated Routes are now stored as attributes in AttributeRegistry
     */
    public function addRoutes(array $routes): void
    {
        // Routes are now handled via addAttributes() as Route::class attributes
        // This method is kept for compatibility but does nothing
    }

    /**
     * Add templates from a batch - streams directly to registry
     */
    public function addTemplates(array $templates): void
    {
        foreach ($templates as $name => $path) {
            $templateMapping = TemplateMapping::create($name, $path);
            $this->templateRegistry->add($templateMapping);
        }
    }

    /**
     * Add data from a DiscoveryRegistry object (for batch processing)
     */
    public function addFromDiscoveryRegistry(DiscoveryRegistry $registry): void
    {
        // Stream data efficiently without creating large intermediate arrays
        foreach ($registry->attributes->getAllTypes() as $type) {
            foreach ($registry->attributes->get($type) as $instance) {
                $this->attributeRegistry->add($type, $instance);
            }
        }

        foreach ($registry->interfaces->getAllInterfaces() as $interface) {
            foreach ($registry->interfaces->get($interface) as $class) {
                $this->interfaceRegistry->add($interface, $class);
            }
        }

        // Routes are now stored as Route::class attributes in AttributeRegistry
        // No separate route handling needed

        foreach ($registry->templates->getAll() as $templateMapping) {
            $this->templateRegistry->add($templateMapping);
        }
    }

    /**
     * Get current attribute count for specific class (for debugging)
     */
    public function getAttributeCount(string $attributeClass): int
    {
        return $this->attributeRegistry->getCount($attributeClass);
    }

    /**
     * Get total collected items count
     */
    public function getTotalItemsCount(): int
    {
        $stats = $this->getMemoryStats();

        return $stats['attributes']['instances'] +
               $stats['interfaces']['implementations'] +
               $stats['templates']['templates'];
    }

    /**
     * Get memory usage statistics
     */
    public function getMemoryStats(): array
    {
        return [
            'attributes' => $this->attributeRegistry->getMemoryStats(),
            'interfaces' => $this->interfaceRegistry->getMemoryStats(),
            'templates' => $this->templateRegistry->getMemoryStats(),
        ];
    }

    /**
     * Create final DiscoveryRegistry object with all collected data (new preferred method)
     */
    public function createRegistry(): DiscoveryRegistry
    {
        // Optimize all registries before returning
        $this->attributeRegistry->optimize();
        $this->interfaceRegistry->optimize();
        $this->templateRegistry->optimize();

        return new DiscoveryRegistry(
            $this->attributeRegistry,
            $this->interfaceRegistry,
            $this->templateRegistry
        );
    }

    /**
     * Clear all collected data (for memory cleanup)
     */
    public function clear(): void
    {
        $this->attributeRegistry->clearCache();
        $this->interfaceRegistry->clearCache();
        $this->templateRegistry->clearCache();
    }

    /**
     * Force optimization of all registries
     */
    public function optimize(): void
    {
        $this->attributeRegistry->optimize();
        $this->interfaceRegistry->optimize();
        $this->templateRegistry->optimize();
    }

    /**
     * Get direct access to registries for advanced usage
     */
    public function getAttributeRegistry(): AttributeRegistry
    {
        return $this->attributeRegistry;
    }

    public function getInterfaceRegistry(): InterfaceRegistry
    {
        return $this->interfaceRegistry;
    }

    public function getTemplateRegistry(): TemplateRegistry
    {
        return $this->templateRegistry;
    }
}
