<?php

declare(strict_types=1);

namespace App\Framework\Mcp\Core\ValueObjects;

/**
 * Concurrency Strategy Value Object
 *
 * Defines how concurrent execution should be managed.
 */
final readonly class ConcurrencyStrategy
{
    public function __construct(
        private int $maxConcurrency = 5,
        private int $memoryThreshold = 200 * 1024 * 1024, // 200MB
        private bool $adaptiveScaling = true,
        private bool $resourceMonitoring = true,
        private bool $optimizeOrder = true,
        private string $loadBalancing = 'round_robin' // round_robin, least_loaded, priority
    ) {
        if ($maxConcurrency <= 0) {
            throw new \InvalidArgumentException('Max concurrency must be positive');
        }

        if ($memoryThreshold <= 0) {
            throw new \InvalidArgumentException('Memory threshold must be positive');
        }
    }

    public function getMaxConcurrency(): int
    {
        return $this->maxConcurrency;
    }

    public function getMemoryThreshold(): int
    {
        return $this->memoryThreshold;
    }

    public function shouldUseAdaptiveScaling(): bool
    {
        return $this->adaptiveScaling;
    }

    public function shouldMonitorResources(): bool
    {
        return $this->resourceMonitoring;
    }

    public function shouldOptimizeOrder(): bool
    {
        return $this->optimizeOrder;
    }

    public function getLoadBalancing(): string
    {
        return $this->loadBalancing;
    }

    public static function conservative(): self
    {
        return new self(
            maxConcurrency: 2,
            memoryThreshold: 50 * 1024 * 1024, // 50MB
            adaptiveScaling: false,
            resourceMonitoring: true,
            optimizeOrder: true
        );
    }

    public static function balanced(): self
    {
        return new self(
            maxConcurrency: 5,
            memoryThreshold: 200 * 1024 * 1024, // 200MB
            adaptiveScaling: true,
            resourceMonitoring: true,
            optimizeOrder: true
        );
    }

    public static function aggressive(): self
    {
        return new self(
            maxConcurrency: 10,
            memoryThreshold: 500 * 1024 * 1024, // 500MB
            adaptiveScaling: true,
            resourceMonitoring: true,
            optimizeOrder: true
        );
    }

    public function toArray(): array
    {
        return [
            'max_concurrency' => $this->maxConcurrency,
            'memory_threshold' => $this->memoryThreshold,
            'memory_threshold_formatted' => $this->formatBytes($this->memoryThreshold),
            'adaptive_scaling' => $this->adaptiveScaling,
            'resource_monitoring' => $this->resourceMonitoring,
            'optimize_order' => $this->optimizeOrder,
            'load_balancing' => $this->loadBalancing,
            'strategy_type' => $this->getStrategyType(),
        ];
    }

    private function getStrategyType(): string
    {
        if ($this->maxConcurrency <= 2) {
            return 'conservative';
        }

        if ($this->maxConcurrency >= 8) {
            return 'aggressive';
        }

        return 'balanced';
    }

    private function formatBytes(int $bytes): string
    {
        if ($bytes === 0) {
            return '0 B';
        }

        $units = ['B', 'KB', 'MB', 'GB'];
        $unitIndex = 0;
        $value = $bytes;

        while ($value >= 1024 && $unitIndex < count($units) - 1) {
            $value /= 1024;
            $unitIndex++;
        }

        return round($value, 2) . ' ' . $units[$unitIndex];
    }
}

/**
 * Concurrency Strategy Enumeration
 */
enum ConcurrencyStrategyType: string
{
    case CONSERVATIVE = 'conservative';
    case BALANCED = 'balanced';
    case AGGRESSIVE = 'aggressive';
    case CUSTOM = 'custom';

    public function getStrategy(): ConcurrencyStrategy
    {
        return match ($this) {
            self::CONSERVATIVE => ConcurrencyStrategy::conservative(),
            self::BALANCED => ConcurrencyStrategy::balanced(),
            self::AGGRESSIVE => ConcurrencyStrategy::aggressive(),
            self::CUSTOM => ConcurrencyStrategy::balanced() // Default fallback
        };
    }
}
