<?php

declare(strict_types=1);

namespace App\Framework\Mcp\Core\ValueObjects;

/**
 * Value Object für MCP Tool Metadaten
 *
 * Ergänzt die Attribut-basierten Metadaten um Runtime-Informationen
 */
final readonly class ToolMetadata
{
    public function __construct(
        public string $name,
        public string $description,
        public array $inputSchema,
        public string $category,
        public array $tags = [],
        public ?string $version = null,
        public bool $cacheable = true,
        public int $defaultCacheTtl = 3600,
        public bool $requiresAuth = false,
        public array $permissions = [],
        public ?float $estimatedExecutionTimeMs = null
    ) {
    }

    /**
     * Erstellt Metadaten aus MCP Attribut-Daten
     */
    public static function fromAttribute(
        string $name,
        string $description,
        array $inputSchema = [],
        string $category = 'general',
        array $tags = []
    ): self {
        return new self(
            name: $name,
            description: $description,
            inputSchema: $inputSchema,
            category: $category,
            tags: $tags
        );
    }

    /**
     * Erstellt erweiterte Metadaten
     */
    public static function extended(
        string $name,
        string $description,
        array $inputSchema,
        string $category,
        array $tags = [],
        ?string $version = null,
        bool $cacheable = true,
        int $defaultCacheTtl = 3600,
        bool $requiresAuth = false,
        array $permissions = [],
        ?float $estimatedExecutionTimeMs = null
    ): self {
        return new self(
            name: $name,
            description: $description,
            inputSchema: $inputSchema,
            category: $category,
            tags: $tags,
            version: $version,
            cacheable: $cacheable,
            defaultCacheTtl: $defaultCacheTtl,
            requiresAuth: $requiresAuth,
            permissions: $permissions,
            estimatedExecutionTimeMs: $estimatedExecutionTimeMs
        );
    }

    /**
     * Fügt Tags hinzu
     */
    public function withTags(array $additionalTags): self
    {
        return new self(
            name: $this->name,
            description: $this->description,
            inputSchema: $this->inputSchema,
            category: $this->category,
            tags: array_unique(array_merge($this->tags, $additionalTags)),
            version: $this->version,
            cacheable: $this->cacheable,
            defaultCacheTtl: $this->defaultCacheTtl,
            requiresAuth: $this->requiresAuth,
            permissions: $this->permissions,
            estimatedExecutionTimeMs: $this->estimatedExecutionTimeMs
        );
    }

    /**
     * Setzt Cache-Konfiguration
     */
    public function withCaching(bool $cacheable, int $ttl = 3600): self
    {
        return new self(
            name: $this->name,
            description: $this->description,
            inputSchema: $this->inputSchema,
            category: $this->category,
            tags: $this->tags,
            version: $this->version,
            cacheable: $cacheable,
            defaultCacheTtl: $ttl,
            requiresAuth: $this->requiresAuth,
            permissions: $this->permissions,
            estimatedExecutionTimeMs: $this->estimatedExecutionTimeMs
        );
    }

    /**
     * Setzt Authentifizierungs-Konfiguration
     */
    public function withAuth(bool $requiresAuth, array $permissions = []): self
    {
        return new self(
            name: $this->name,
            description: $this->description,
            inputSchema: $this->inputSchema,
            category: $this->category,
            tags: $this->tags,
            version: $this->version,
            cacheable: $this->cacheable,
            defaultCacheTtl: $this->defaultCacheTtl,
            requiresAuth: $requiresAuth,
            permissions: $permissions,
            estimatedExecutionTimeMs: $this->estimatedExecutionTimeMs
        );
    }

    /**
     * Setzt geschätzte Ausführungszeit
     */
    public function withEstimatedExecutionTime(float $timeMs): self
    {
        return new self(
            name: $this->name,
            description: $this->description,
            inputSchema: $this->inputSchema,
            category: $this->category,
            tags: $this->tags,
            version: $this->version,
            cacheable: $this->cacheable,
            defaultCacheTtl: $this->defaultCacheTtl,
            requiresAuth: $this->requiresAuth,
            permissions: $this->permissions,
            estimatedExecutionTimeMs: $timeMs
        );
    }

    /**
     * Prüft ob Tool eine bestimmte Permission benötigt
     */
    public function hasPermission(string $permission): bool
    {
        return in_array($permission, $this->permissions, true);
    }

    /**
     * Prüft ob Tool einen bestimmten Tag hat
     */
    public function hasTag(string $tag): bool
    {
        return in_array($tag, $this->tags, true);
    }

    /**
     * Prüft ob Tool langsam ist (> 1000ms geschätzte Ausführungszeit)
     */
    public function isSlow(): bool
    {
        return $this->estimatedExecutionTimeMs !== null && $this->estimatedExecutionTimeMs > 1000.0;
    }

    /**
     * Konvertiert zu Array für Serialization
     */
    public function toArray(): array
    {
        return [
            'name' => $this->name,
            'description' => $this->description,
            'input_schema' => $this->inputSchema,
            'category' => $this->category,
            'tags' => $this->tags,
            'version' => $this->version,
            'cacheable' => $this->cacheable,
            'default_cache_ttl' => $this->defaultCacheTtl,
            'requires_auth' => $this->requiresAuth,
            'permissions' => $this->permissions,
            'estimated_execution_time_ms' => $this->estimatedExecutionTimeMs,
        ];
    }
}
