<?php

declare(strict_types=1);

namespace App\Framework\MachineLearning\ValueObjects;

/**
 * Types of features for ML analysis across different domains
 *
 * This enum is domain-agnostic and categorizes features by their characteristics
 * rather than their specific domain (WAF, Query, Performance, etc.)
 *
 * Feature categories are organized by:
 * - FREQUENCY: Count/rate-based measurements
 * - PATTERN: Structural/behavioral patterns
 * - TEMPORAL: Time-based patterns
 * - PERFORMANCE: Speed/efficiency metrics
 * - RESOURCE: Resource utilization metrics
 * - ERROR: Error/failure patterns
 * - GEOGRAPHIC: Location-based patterns
 */
enum FeatureType: string
{
    // Frequency-based features
    case FREQUENCY = 'frequency';
    case RATE = 'rate';
    case VOLUME = 'volume';

    // Pattern-based features
    case STRUCTURAL_PATTERN = 'structural_pattern';
    case BEHAVIORAL_PATTERN = 'behavioral_pattern';
    case SEQUENCE_PATTERN = 'sequence_pattern';
    case ACCESS_PATTERN = 'access_pattern';

    // Temporal features
    case TEMPORAL = 'temporal';
    case TIME_DISTRIBUTION = 'time_distribution';
    case DURATION = 'duration';

    // Performance features
    case LATENCY = 'latency';
    case THROUGHPUT = 'throughput';
    case EFFICIENCY = 'efficiency';

    // Resource utilization features
    case MEMORY_USAGE = 'memory_usage';
    case CPU_USAGE = 'cpu_usage';
    case CACHE_UTILIZATION = 'cache_utilization';
    case CONNECTION_USAGE = 'connection_usage';

    // Error/failure features
    case ERROR_RATE = 'error_rate';
    case FAILURE_PATTERN = 'failure_pattern';
    case EXCEPTION_PATTERN = 'exception_pattern';

    // Geographic features
    case GEOGRAPHIC_DISTRIBUTION = 'geographic_distribution';
    case LOCATION_PATTERN = 'location_pattern';

    // Session/state features
    case SESSION_PATTERN = 'session_pattern';
    case STATE_TRANSITION = 'state_transition';

    // Diversity/entropy features
    case DIVERSITY = 'diversity';
    case ENTROPY = 'entropy';
    case UNIQUENESS = 'uniqueness';

    /**
     * Get human-readable description
     */
    public function getDescription(): string
    {
        return match ($this) {
            self::FREQUENCY => 'Event occurrence frequency',
            self::RATE => 'Event rate over time',
            self::VOLUME => 'Total volume or quantity',

            self::STRUCTURAL_PATTERN => 'Structural composition patterns',
            self::BEHAVIORAL_PATTERN => 'Behavioral characteristic patterns',
            self::SEQUENCE_PATTERN => 'Sequential order patterns',
            self::ACCESS_PATTERN => 'Access and usage patterns',

            self::TEMPORAL => 'Time-based behavior',
            self::TIME_DISTRIBUTION => 'Distribution over time',
            self::DURATION => 'Time duration measurements',

            self::LATENCY => 'Response/execution time',
            self::THROUGHPUT => 'Processing throughput rate',
            self::EFFICIENCY => 'Efficiency and optimization metrics',

            self::MEMORY_USAGE => 'Memory consumption patterns',
            self::CPU_USAGE => 'CPU utilization patterns',
            self::CACHE_UTILIZATION => 'Cache hit/miss patterns',
            self::CONNECTION_USAGE => 'Connection pool usage',

            self::ERROR_RATE => 'Error occurrence rate',
            self::FAILURE_PATTERN => 'Failure and fault patterns',
            self::EXCEPTION_PATTERN => 'Exception occurrence patterns',

            self::GEOGRAPHIC_DISTRIBUTION => 'Geographic location distribution',
            self::LOCATION_PATTERN => 'Location-based patterns',

            self::SESSION_PATTERN => 'Session management patterns',
            self::STATE_TRANSITION => 'State change patterns',

            self::DIVERSITY => 'Value diversity metrics',
            self::ENTROPY => 'Information entropy metrics',
            self::UNIQUENESS => 'Uniqueness and cardinality metrics',
        };
    }

    /**
     * Get feature extraction weight (importance) for this feature type
     */
    public function getWeight(): float
    {
        return match ($this) {
            // High importance (critical features)
            self::FREQUENCY, self::ERROR_RATE, self::LATENCY => 0.15,

            // Medium-high importance
            self::BEHAVIORAL_PATTERN, self::THROUGHPUT, self::FAILURE_PATTERN => 0.12,

            // Medium importance
            self::RATE, self::TEMPORAL, self::STRUCTURAL_PATTERN,
            self::SESSION_PATTERN, self::MEMORY_USAGE => 0.10,

            // Medium-low importance
            self::VOLUME, self::ACCESS_PATTERN, self::EFFICIENCY,
            self::GEOGRAPHIC_DISTRIBUTION => 0.08,

            // Lower importance (supplementary features)
            self::DURATION, self::CPU_USAGE, self::CACHE_UTILIZATION,
            self::SEQUENCE_PATTERN, self::LOCATION_PATTERN => 0.07,

            // Low importance (contextual features)
            self::TIME_DISTRIBUTION, self::CONNECTION_USAGE,
            self::EXCEPTION_PATTERN, self::STATE_TRANSITION,
            self::DIVERSITY, self::ENTROPY, self::UNIQUENESS => 0.05,
        };
    }

    /**
     * Get minimum sample size needed for reliable analysis
     */
    public function getMinSampleSize(): int
    {
        return match ($this) {
            // High sample requirements (time-based patterns)
            self::TEMPORAL, self::TIME_DISTRIBUTION => 100,

            // Medium-high requirements (frequency/rate based)
            self::FREQUENCY, self::RATE, self::LATENCY,
            self::SESSION_PATTERN => 50,

            // Medium requirements (pattern-based)
            self::BEHAVIORAL_PATTERN, self::STRUCTURAL_PATTERN,
            self::ERROR_RATE, self::THROUGHPUT => 30,

            // Medium-low requirements
            self::VOLUME, self::ACCESS_PATTERN, self::FAILURE_PATTERN,
            self::MEMORY_USAGE, self::CPU_USAGE => 25,

            // Low requirements (simple patterns)
            self::DURATION, self::EFFICIENCY, self::CACHE_UTILIZATION,
            self::SEQUENCE_PATTERN, self::EXCEPTION_PATTERN,
            self::DIVERSITY, self::ENTROPY => 20,

            // Minimal requirements
            self::GEOGRAPHIC_DISTRIBUTION, self::LOCATION_PATTERN,
            self::CONNECTION_USAGE, self::STATE_TRANSITION,
            self::UNIQUENESS => 10,
        };
    }

    /**
     * Get analysis window duration in seconds
     */
    public function getAnalysisWindow(): int
    {
        return match ($this) {
            // 24 hours (daily patterns)
            self::TEMPORAL, self::TIME_DISTRIBUTION => 86400,

            // 2 hours (long-term trends)
            self::GEOGRAPHIC_DISTRIBUTION, self::LOCATION_PATTERN => 7200,

            // 1 hour (medium-term patterns)
            self::BEHAVIORAL_PATTERN, self::SESSION_PATTERN,
            self::STATE_TRANSITION => 3600,

            // 30 minutes (short-term patterns)
            self::STRUCTURAL_PATTERN, self::ACCESS_PATTERN,
            self::DIVERSITY, self::UNIQUENESS => 1800,

            // 15 minutes (medium-frequency)
            self::VOLUME, self::SEQUENCE_PATTERN, self::ENTROPY,
            self::MEMORY_USAGE, self::CPU_USAGE => 900,

            // 10 minutes (high-frequency)
            self::ERROR_RATE, self::FAILURE_PATTERN, self::EXCEPTION_PATTERN,
            self::LATENCY, self::THROUGHPUT => 600,

            // 5 minutes (real-time/critical)
            self::FREQUENCY, self::RATE, self::EFFICIENCY,
            self::CACHE_UTILIZATION, self::CONNECTION_USAGE => 300,

            // 2 minutes (very high frequency)
            self::DURATION => 120,
        };
    }

    /**
     * Check if this feature type requires real-time analysis
     */
    public function requiresRealTime(): bool
    {
        return match ($this) {
            self::FREQUENCY,
            self::RATE,
            self::ERROR_RATE,
            self::FAILURE_PATTERN,
            self::LATENCY,
            self::THROUGHPUT => true,
            default => false
        };
    }

    /**
     * Check if this feature type is performance-related
     */
    public function isPerformanceMetric(): bool
    {
        return match ($this) {
            self::LATENCY,
            self::THROUGHPUT,
            self::EFFICIENCY,
            self::MEMORY_USAGE,
            self::CPU_USAGE,
            self::CACHE_UTILIZATION,
            self::CONNECTION_USAGE,
            self::DURATION => true,
            default => false
        };
    }

    /**
     * Check if this feature type is error/failure-related
     */
    public function isErrorMetric(): bool
    {
        return match ($this) {
            self::ERROR_RATE,
            self::FAILURE_PATTERN,
            self::EXCEPTION_PATTERN => true,
            default => false
        };
    }

    /**
     * Check if this feature type is pattern-based
     */
    public function isPatternMetric(): bool
    {
        return match ($this) {
            self::STRUCTURAL_PATTERN,
            self::BEHAVIORAL_PATTERN,
            self::SEQUENCE_PATTERN,
            self::ACCESS_PATTERN,
            self::SESSION_PATTERN,
            self::STATE_TRANSITION => true,
            default => false
        };
    }

    /**
     * Get all feature types as array
     *
     * @return string[]
     */
    public static function getAll(): array
    {
        return array_map(fn($case) => $case->value, self::cases());
    }

    /**
     * Get real-time feature types
     *
     * @return self[]
     */
    public static function getRealTime(): array
    {
        return array_filter(self::cases(), fn($case) => $case->requiresRealTime());
    }

    /**
     * Get batch analysis feature types
     *
     * @return self[]
     */
    public static function getBatch(): array
    {
        return array_filter(self::cases(), fn($case) => !$case->requiresRealTime());
    }

    /**
     * Get performance-related feature types
     *
     * @return self[]
     */
    public static function getPerformanceMetrics(): array
    {
        return array_filter(self::cases(), fn($case) => $case->isPerformanceMetric());
    }

    /**
     * Get error-related feature types
     *
     * @return self[]
     */
    public static function getErrorMetrics(): array
    {
        return array_filter(self::cases(), fn($case) => $case->isErrorMetric());
    }

    /**
     * Get pattern-based feature types
     *
     * @return self[]
     */
    public static function getPatternMetrics(): array
    {
        return array_filter(self::cases(), fn($case) => $case->isPatternMetric());
    }
}
