<?php

declare(strict_types=1);

namespace App\Framework\Discovery\Enhanced\ValueObjects;

use App\Framework\Discovery\ValueObjects\DiscoveryContext;

/**
 * Discovery Plan for optimized component discovery
 *
 * Defines the strategy and parameters for enhanced discovery execution.
 */
final readonly class DiscoveryPlan
{
    public function __construct(
        private array $paths,
        private array $attributes,
        private DiscoveryContext $discoveryContext,
        private PlanStrategy $strategy,
        private array $optimizations = [],
        private array $predictions = [],
        private array $metadata = []
    ) {
    }

    public function getPaths(): array
    {
        return $this->paths;
    }

    public function getAttributes(): array
    {
        return $this->attributes;
    }

    public function getDiscoveryContext(): DiscoveryContext
    {
        return $this->discoveryContext;
    }

    public function getStrategy(): PlanStrategy
    {
        return $this->strategy;
    }

    public function getOptimizations(): array
    {
        return $this->optimizations;
    }

    public function getPredictions(): array
    {
        return $this->predictions;
    }

    public function getMetadata(): array
    {
        return $this->metadata;
    }

    /**
     * Create an optimized plan for performance
     */
    public static function optimized(
        array $paths,
        array $attributes = [],
        array $optimizations = []
    ): self {
        return new self(
            paths: $paths,
            attributes: $attributes,
            discoveryContext: DiscoveryContext::default(),
            strategy: PlanStrategy::PERFORMANCE_OPTIMIZED,
            optimizations: array_merge([
                'memory_efficient' => true,
                'cache_aggressive' => true,
                'parallel_processing' => true,
            ], $optimizations)
        );
    }

    /**
     * Create a comprehensive plan for thorough discovery
     */
    public static function comprehensive(
        array $paths,
        array $attributes = []
    ): self {
        return new self(
            paths: $paths,
            attributes: $attributes,
            discoveryContext: DiscoveryContext::comprehensive(),
            strategy: PlanStrategy::COMPREHENSIVE,
            optimizations: [
                'deep_analysis' => true,
                'dependency_mapping' => true,
                'pattern_recognition' => true,
            ]
        );
    }

    /**
     * Create a minimal plan for basic discovery
     */
    public static function minimal(array $paths): self
    {
        return new self(
            paths: $paths,
            attributes: [],
            discoveryContext: DiscoveryContext::minimal(),
            strategy: PlanStrategy::MINIMAL,
            optimizations: [
                'cache_only' => true,
                'skip_analysis' => true,
            ]
        );
    }

    /**
     * Check if a specific optimization is enabled
     */
    public function hasOptimization(string $optimization): bool
    {
        return isset($this->optimizations[$optimization]) &&
               $this->optimizations[$optimization] === true;
    }

    /**
     * Get optimization value
     */
    public function getOptimization(string $key, mixed $default = null): mixed
    {
        return $this->optimizations[$key] ?? $default;
    }

    /**
     * Create a new plan with additional optimizations
     */
    public function withOptimizations(array $additionalOptimizations): self
    {
        return new self(
            paths: $this->paths,
            attributes: $this->attributes,
            discoveryContext: $this->discoveryContext,
            strategy: $this->strategy,
            optimizations: array_merge($this->optimizations, $additionalOptimizations),
            predictions: $this->predictions,
            metadata: $this->metadata
        );
    }

    /**
     * Create a new plan with predictions
     */
    public function withPredictions(array $predictions): self
    {
        return new self(
            paths: $this->paths,
            attributes: $this->attributes,
            discoveryContext: $this->discoveryContext,
            strategy: $this->strategy,
            optimizations: $this->optimizations,
            predictions: $predictions,
            metadata: $this->metadata
        );
    }

    /**
     * Get plan as array for serialization
     */
    public function toArray(): array
    {
        return [
            'paths' => $this->paths,
            'attributes' => $this->attributes,
            'strategy' => $this->strategy->value,
            'optimizations' => $this->optimizations,
            'predictions' => $this->predictions,
            'metadata' => $this->metadata,
        ];
    }
}
