<?php

declare(strict_types=1);

namespace App\Framework\Discovery\ValueObjects;

/**
 * Memory management strategies for Discovery operations
 *
 * Defines different approaches to memory management based on
 * system constraints and operation requirements.
 */
enum MemoryStrategy: string
{
    /**
     * Adaptive strategy - adjusts based on memory pressure
     * Monitors memory usage and adapts chunk sizes dynamically
     */
    case ADAPTIVE = 'adaptive';

    /**
     * Conservative strategy - prioritizes memory conservation
     * Uses small chunks and frequent cleanup
     */
    case CONSERVATIVE = 'conservative';

    /**
     * Aggressive strategy - prioritizes speed over memory
     * Uses large chunks and minimal cleanup
     */
    case AGGRESSIVE = 'aggressive';

    /**
     * Streaming strategy - minimal memory footprint
     * Processes items one by one with immediate cleanup
     */
    case STREAMING = 'streaming';

    /**
     * Batch strategy - balanced approach
     * Fixed batch sizes with predictable memory usage
     */
    case BATCH = 'batch';

    /**
     * Get default chunk size for this strategy
     */
    public function getDefaultChunkSize(): int
    {
        return match ($this) {
            self::ADAPTIVE => 100,     // Will be adjusted based on memory pressure
            self::CONSERVATIVE => 25,  // Small chunks
            self::AGGRESSIVE => 500,   // Large chunks
            self::STREAMING => 1,      // One item at a time
            self::BATCH => 100,        // Standard batch size
        };
    }

    /**
     * Get memory pressure threshold for this strategy
     */
    public function getMemoryPressureThreshold(): float
    {
        return match ($this) {
            self::ADAPTIVE => 0.7,     // Adapt when 70% memory used
            self::CONSERVATIVE => 0.5,  // Conservative at 50%
            self::AGGRESSIVE => 0.9,   // Only care at 90%
            self::STREAMING => 0.8,    // Moderate threshold
            self::BATCH => 0.75,       // Standard threshold
        };
    }

    /**
     * Get cleanup frequency for this strategy
     */
    public function getCleanupFrequency(): int
    {
        return match ($this) {
            self::ADAPTIVE => 50,      // Every 50 items (adaptive)
            self::CONSERVATIVE => 10,  // Frequent cleanup
            self::AGGRESSIVE => 200,   // Minimal cleanup
            self::STREAMING => 1,      // Cleanup after each item
            self::BATCH => 100,        // Standard cleanup
        };
    }

    /**
     * Check if strategy supports dynamic adjustment
     */
    public function supportsDynamicAdjustment(): bool
    {
        return match ($this) {
            self::ADAPTIVE => true,
            self::CONSERVATIVE,
            self::AGGRESSIVE,
            self::STREAMING,
            self::BATCH => false,
        };
    }

    /**
     * Get strategy description for logging/debugging
     */
    public function getDescription(): string
    {
        return match ($this) {
            self::ADAPTIVE => 'Dynamically adjusts based on memory pressure and system performance',
            self::CONSERVATIVE => 'Prioritizes memory conservation with small chunks and frequent cleanup',
            self::AGGRESSIVE => 'Prioritizes speed with large chunks and minimal cleanup overhead',
            self::STREAMING => 'Minimal memory footprint processing items one by one',
            self::BATCH => 'Balanced approach with fixed batch sizes and predictable memory usage',
        };
    }

    /**
     * Suggest strategy based on system constraints
     */
    public static function suggestForSystem(int $availableMemoryMB, int $itemCount): self
    {
        // Very low memory systems
        if ($availableMemoryMB < 64) {
            return self::STREAMING;
        }

        // Low memory or high item count
        if ($availableMemoryMB < 128 || $itemCount > 10000) {
            return self::CONSERVATIVE;
        }

        // High memory systems with moderate item count
        if ($availableMemoryMB > 512 && $itemCount < 1000) {
            return self::AGGRESSIVE;
        }

        // Variable workloads
        if ($itemCount > 5000) {
            return self::ADAPTIVE;
        }

        // Default balanced approach
        return self::BATCH;
    }

    /**
     * Suggest strategy based on discovery configuration
     */
    public static function suggestForDiscovery(
        int $estimatedFileCount,
        int $memoryLimitMB,
        bool $enablePerformanceTracking = false
    ): self {
        // Performance tracking adds memory overhead
        $effectiveMemory = $enablePerformanceTracking
            ? (int)($memoryLimitMB * 0.8)
            : $memoryLimitMB;

        // Large codebases need adaptive or conservative approaches
        if ($estimatedFileCount > 5000) {
            return $effectiveMemory > 256 ? self::ADAPTIVE : self::CONSERVATIVE;
        }

        // Medium codebases can use batch processing
        if ($estimatedFileCount > 1000) {
            return $effectiveMemory > 128 ? self::BATCH : self::CONSERVATIVE;
        }

        // Small codebases can afford aggressive processing
        if ($estimatedFileCount < 500) {
            return $effectiveMemory > 64 ? self::AGGRESSIVE : self::BATCH;
        }

        // Default to adaptive for unknown workloads
        return self::ADAPTIVE;
    }
}
