<?php
declare(strict_types=1);

namespace App\Framework\Discovery\Results;

/**
 * Einheitliche Klasse für alle Discovery-Ergebnisse
 */
final class DiscoveryResults
{
    private array $attributeResults = [];
    private array $interfaceImplementations = [];
    private array $routes = [];
    private array $templates = [];
    private array $additionalResults = [];

    public function __construct(
        array $attributeResults = [],
        array $interfaceImplementations = [],
        array $routes = [],
        array $templates = [],
        array $additionalResults = []
    ) {
        $this->attributeResults = $attributeResults;
        $this->interfaceImplementations = $interfaceImplementations;
        $this->routes = $routes;
        $this->templates = $templates;
        $this->additionalResults = $additionalResults;
    }

    // === Attribute Results ===

    public function setAttributeResults(array $results): void
    {
        $this->attributeResults = $results;
    }

    public function addAttributeResult(string $attributeClass, array $data): void
    {
        $this->attributeResults[$attributeClass][] = $data;
    }

    public function getAttributeResults(string $attributeClass): array
    {
        return $this->attributeResults[$attributeClass] ?? [];
    }

    public function getAllAttributeResults(): array
    {
        return $this->attributeResults;
    }

    public function hasAttributeResults(string $attributeClass): bool
    {
        return !empty($this->attributeResults[$attributeClass]);
    }

    // === Interface Implementations ===

    public function setInterfaceImplementations(array $implementations): void
    {
        $this->interfaceImplementations = $implementations;
    }

    public function addInterfaceImplementation(string $interface, string $className): void
    {
        if (!isset($this->interfaceImplementations[$interface])) {
            $this->interfaceImplementations[$interface] = [];
        }

        if (!in_array($className, $this->interfaceImplementations[$interface])) {
            $this->interfaceImplementations[$interface][] = $className;
        }
    }

    public function getInterfaceImplementations(string $interface): array
    {
        return $this->interfaceImplementations[$interface] ?? [];
    }

    public function getAllInterfaceImplementations(): array
    {
        return $this->interfaceImplementations;
    }

    // === Routes ===

    public function setRoutes(array $routes): void
    {
        $this->routes = $routes;
    }

    public function getRoutes(): array
    {
        return $this->routes;
    }

    // === Templates ===

    public function setTemplates(array $templates): void
    {
        $this->templates = $templates;
    }

    public function getTemplates(): array
    {
        return $this->templates;
    }

    // === Additional Results ===

    public function setAdditionalResult(string $key, mixed $value): void
    {
        $this->additionalResults[$key] = $value;
    }

    public function getAdditionalResult(string $key, mixed $default = null): mixed
    {
        return $this->additionalResults[$key] ?? $default;
    }

    public function has(string $key): bool
    {
        return isset($this->additionalResults[$key]) ||
            isset($this->attributeResults[$key]) ||
            isset($this->interfaceImplementations[$key]) ||
            isset($this->routes[$key]) ||
            isset($this->templates[$key]);
    }

    // === Compatibility with old ProcessedResults ===

    /**
     * Kompatibilitätsmethode für bestehenden Code
     */
    public function get(string $key): array
    {
        // Direkte Suche nach dem Key
        if (isset($this->attributeResults[$key])) {
            return $this->attributeResults[$key];
        }

        // Versuche auch mit führendem Backslash
        $keyWithBackslash = '\\' . ltrim($key, '\\');
        if (isset($this->attributeResults[$keyWithBackslash])) {
            return $this->attributeResults[$keyWithBackslash];
        }

        // Versuche ohne führenden Backslash
        $keyWithoutBackslash = ltrim($key, '\\');
        if (isset($this->attributeResults[$keyWithoutBackslash])) {
            return $this->attributeResults[$keyWithoutBackslash];
        }

        // Für Interfaces (z.B. Initializer::class)
        if (isset($this->interfaceImplementations[$key])) {
            return array_map(function($className) {
                return ['class' => $className];
            }, $this->interfaceImplementations[$key]);
        }

        if (isset($this->interfaceImplementations[$keyWithBackslash])) {
            return array_map(function($className) {
                return ['class' => $className];
            }, $this->interfaceImplementations[$keyWithBackslash]);
        }

        if (isset($this->interfaceImplementations[$keyWithoutBackslash])) {
            return array_map(function($className) {
                return ['class' => $className];
            }, $this->interfaceImplementations[$keyWithoutBackslash]);
        }

        // Für spezielle Keys
        switch ($key) {
            case 'routes':
                return $this->routes;
            case 'templates':
                return $this->templates;
        }

        return $this->additionalResults[$key] ?? [];
    }

    // === Serialization ===

    public function toArray(): array
    {
        return [
            'attributes' => $this->attributeResults,
            'interfaces' => $this->interfaceImplementations,
            'routes' => $this->routes,
            'templates' => $this->templates,
            'additional' => $this->additionalResults,
        ];
    }

    public static function fromArray(array $data): self
    {
        return new self(
            $data['attributes'] ?? [],
            $data['interfaces'] ?? [],
            $data['routes'] ?? [],
            $data['templates'] ?? [],
            $data['additional'] ?? []
        );
    }

/*    public function __serialize(): array
    {
        return $this->toArray();
    }

    public function __unserialize(array $data): void
    {
        $this->attributeResults = $data['attributes'] ?? [];
        $this->interfaceImplementations = $data['interfaces'] ?? [];
        $this->routes = $data['routes'] ?? [];
        $this->templates = $data['templates'] ?? [];
        $this->additionalResults = $data['additional'] ?? [];
    }*/

    // === Utility Methods ===

    public function isEmpty(): bool
    {
        return empty($this->attributeResults)
            && empty($this->interfaceImplementations)
            && empty($this->routes)
            && empty($this->templates)
            && empty($this->additionalResults);
    }

    public function merge(DiscoveryResults $other): self
    {
        return new self(
            array_merge_recursive($this->attributeResults, $other->attributeResults),
            array_merge_recursive($this->interfaceImplementations, $other->interfaceImplementations),
            array_merge($this->routes, $other->routes),
            array_merge($this->templates, $other->templates),
            array_merge($this->additionalResults, $other->additionalResults)
        );
    }

    /**
     * Sortiert Interface-Implementierungen für konsistente Ergebnisse
     */
    public function sortInterfaceImplementations(): void
    {
        foreach ($this->interfaceImplementations as &$implementations) {
            sort($implementations);
            $implementations = array_unique($implementations);
        }
    }
}
