<?php

declare(strict_types=1);

namespace App\Framework\Discovery\ValueObjects;

/**
 * Cache tier enumeration for tiered caching strategy
 *
 * Defines different cache tiers with specific retention, compression,
 * and access characteristics optimized for different usage patterns.
 */
enum CacheTier: string
{
    case HOT = 'hot';           // Frequently accessed, small items, no compression
    case WARM = 'warm';         // Moderately accessed, light compression
    case COLD = 'cold';         // Rarely accessed, medium compression
    case ARCHIVE = 'archive';   // Very rarely accessed, maximum compression

    /**
     * Get compression level for this tier
     */
    public function getCompressionLevel(): CompressionLevel
    {
        return match ($this) {
            self::HOT => CompressionLevel::NONE,
            self::WARM => CompressionLevel::LOW,
            self::COLD => CompressionLevel::MEDIUM,
            self::ARCHIVE => CompressionLevel::MAXIMUM
        };
    }

    /**
     * Get TTL multiplier for this tier
     */
    public function getTtlMultiplier(): float
    {
        return match ($this) {
            self::HOT => 0.5,      // Shorter TTL for hot data
            self::WARM => 1.0,     // Normal TTL
            self::COLD => 2.0,     // Longer TTL for cold data
            self::ARCHIVE => 5.0   // Very long TTL for archived data
        };
    }

    /**
     * Get expected access frequency for this tier
     */
    public function getExpectedAccessFrequency(): float
    {
        return match ($this) {
            self::HOT => 20.0,      // 20+ accesses per hour
            self::WARM => 5.0,      // 5-20 accesses per hour
            self::COLD => 1.0,      // 1-5 accesses per hour
            self::ARCHIVE => 0.1    // < 1 access per hour
        };
    }

    /**
     * Get maximum item size for this tier
     */
    public function getMaxItemSize(): int
    {
        return match ($this) {
            self::HOT => 10 * 1024,      // 10KB
            self::WARM => 100 * 1024,    // 100KB
            self::COLD => 1024 * 1024,   // 1MB
            self::ARCHIVE => PHP_INT_MAX // No limit
        };
    }

    /**
     * Get priority for this tier (higher = more important)
     */
    public function getPriority(): int
    {
        return match ($this) {
            self::HOT => 100,
            self::WARM => 75,
            self::COLD => 50,
            self::ARCHIVE => 25
        };
    }

    /**
     * Get higher tier (for promotion)
     */
    public function getHigherTier(): ?self
    {
        return match ($this) {
            self::ARCHIVE => self::COLD,
            self::COLD => self::WARM,
            self::WARM => self::HOT,
            self::HOT => null // Already highest
        };
    }

    /**
     * Get lower tier (for demotion)
     */
    public function getLowerTier(): ?self
    {
        return match ($this) {
            self::HOT => self::WARM,
            self::WARM => self::COLD,
            self::COLD => self::ARCHIVE,
            self::ARCHIVE => null // Already lowest
        };
    }

    /**
     * Check if this tier should be used under memory pressure
     */
    public function isRecommendedUnderMemoryPressure(float $pressure): bool
    {
        return match ($this) {
            self::HOT => $pressure < 0.6,      // Only under low pressure
            self::WARM => $pressure < 0.8,     // Under moderate pressure
            self::COLD => $pressure < 0.9,     // Under high pressure
            self::ARCHIVE => true              // Always acceptable
        };
    }

    /**
     * Get description of this tier
     */
    public function getDescription(): string
    {
        return match ($this) {
            self::HOT => 'High-frequency access, minimal compression, short TTL',
            self::WARM => 'Moderate access, light compression, normal TTL',
            self::COLD => 'Low-frequency access, medium compression, long TTL',
            self::ARCHIVE => 'Rare access, maximum compression, very long TTL'
        };
    }

    /**
     * Convert to corresponding cache level
     */
    public function toCacheLevel(): CacheLevel
    {
        return match ($this) {
            self::HOT => CacheLevel::EXTENDED,
            self::WARM => CacheLevel::NORMAL,
            self::COLD => CacheLevel::COMPRESSED,
            self::ARCHIVE => CacheLevel::MINIMAL
        };
    }

    /**
     * Suggest tier based on data characteristics
     */
    public static function suggest(int $dataSize, float $accessFrequency, float $memoryPressure): self
    {
        // Under high memory pressure, prefer lower tiers
        if ($memoryPressure > 0.85) {
            return $dataSize > 100 * 1024 ? self::ARCHIVE : self::COLD;
        }

        // Normal tier assignment
        return match (true) {
            $dataSize <= 10 * 1024 && $accessFrequency >= 20 => self::HOT,
            $dataSize <= 100 * 1024 && $accessFrequency >= 5 => self::WARM,
            $dataSize <= 1024 * 1024 && $accessFrequency >= 1 => self::COLD,
            default => self::ARCHIVE
        };
    }

    /**
     * Get all tiers ordered by priority (highest first)
     */
    public static function orderedByPriority(): array
    {
        return [self::HOT, self::WARM, self::COLD, self::ARCHIVE];
    }

    /**
     * Get memory-efficient tiers for cleanup
     */
    public static function getMemoryEfficientTiers(): array
    {
        return [self::ARCHIVE, self::COLD]; // Most compressed tiers
    }
}
