<?php

declare(strict_types=1);

namespace App\Framework\RateLimit;

use App\Framework\Core\ValueObjects\Duration;
use App\Framework\Core\ValueObjects\Percentage;
use App\Framework\Core\ValueObjects\Timestamp;

/**
 * Rate Limit Result with Advanced WAF Intelligence
 *
 * Enhanced with sophisticated threat analysis, attack pattern detection,
 * and adaptive response capabilities from the WAF system.
 */
readonly class RateLimitResult
{
    public function __construct(
        private bool $allowed,
        private int $limit,
        private int $current,
        private ?int $retryAfter = null,

        // WAF Intelligence Extensions
        public ?Percentage $threatScore = null,
        public ?float $baselineDeviation = null,
        public array $attackPatterns = [],
        public array $anomalyIndicators = [],
        public ?Duration $processingTime = null,
        public ?Timestamp $analysisTimestamp = null,
        public ?string $clientIp = null,
        public ?string $requestPath = null,
        public ?string $userAgent = null,

        // Traffic Analysis Extensions
        public ?array $trafficAnalysis = null,
        public ?array $burstAnalysis = null,
        public ?array $geoAnalysis = null,
        public ?float $confidence = null,

        // Adaptive Response Data
        public ?string $recommendedAction = null,
        public ?Duration $adaptiveRetryAfter = null,
        public array $responseStrategies = [],

        // Performance Metrics
        public ?array $performanceMetrics = null
    ) {
    }

    public static function allowed(int $limit, int $current): self
    {
        return new self(
            allowed: true,
            limit: $limit,
            current: $current
        );
    }

    public static function exceeded(int $limit, int $current, int $retryAfter): self
    {
        return new self(
            allowed: false,
            limit: $limit,
            current: $current,
            retryAfter: $retryAfter
        );
    }

    /**
     * Create result with advanced threat analysis
     */
    public static function withThreatAnalysis(
        bool $allowed,
        int $limit,
        int $current,
        array $analysisData = [],
        ?int $retryAfter = null
    ): self {
        return new self(
            allowed: $allowed,
            limit: $limit,
            current: $current,
            retryAfter: $retryAfter,
            threatScore: isset($analysisData['threat_score']) ? Percentage::from($analysisData['threat_score']) : null,
            baselineDeviation: $analysisData['baseline_deviation'] ?? null,
            attackPatterns: $analysisData['attack_patterns'] ?? [],
            anomalyIndicators: $analysisData['anomaly_indicators'] ?? [],
            processingTime: $analysisData['processing_time'] ?? null,
            analysisTimestamp: $analysisData['timestamp'] ?? null,
            clientIp: $analysisData['client_ip'] ?? null,
            requestPath: $analysisData['request_path'] ?? null,
            userAgent: $analysisData['user_agent'] ?? null,
            trafficAnalysis: $analysisData['traffic_analysis'] ?? null,
            burstAnalysis: $analysisData['burst_analysis'] ?? null,
            geoAnalysis: $analysisData['geo_analysis'] ?? null,
            confidence: $analysisData['confidence'] ?? null,
            recommendedAction: $analysisData['recommended_action'] ?? ($allowed ? 'allow' : 'block'),
            adaptiveRetryAfter: $analysisData['adaptive_retry_after'] ?? null,
            responseStrategies: $analysisData['response_strategies'] ?? [],
            performanceMetrics: $analysisData['performance_metrics'] ?? null
        );
    }

    /**
     * Create suspicious result (allowed but flagged)
     */
    public static function suspicious(
        int $limit,
        int $current,
        array $suspicionData = []
    ): self {
        return new self(
            allowed: true,
            limit: $limit,
            current: $current,
            threatScore: isset($suspicionData['threat_score']) ? Percentage::from($suspicionData['threat_score']) : Percentage::from(60.0),
            baselineDeviation: $suspicionData['baseline_deviation'] ?? null,
            attackPatterns: $suspicionData['attack_patterns'] ?? [],
            anomalyIndicators: $suspicionData['anomaly_indicators'] ?? [],
            processingTime: $suspicionData['processing_time'] ?? null,
            analysisTimestamp: $suspicionData['timestamp'] ?? null,
            clientIp: $suspicionData['client_ip'] ?? null,
            requestPath: $suspicionData['request_path'] ?? null,
            userAgent: $suspicionData['user_agent'] ?? null,
            trafficAnalysis: $suspicionData['traffic_analysis'] ?? null,
            burstAnalysis: $suspicionData['burst_analysis'] ?? null,
            geoAnalysis: $suspicionData['geo_analysis'] ?? null,
            confidence: $suspicionData['confidence'] ?? null,
            recommendedAction: 'monitor',
            responseStrategies: $suspicionData['response_strategies'] ?? ['increased_monitoring', 'captcha_challenge'],
            performanceMetrics: $suspicionData['performance_metrics'] ?? null
        );
    }

    public function isAllowed(): bool
    {
        return $this->allowed;
    }

    public function isExceeded(): bool
    {
        return ! $this->allowed;
    }

    public function getLimit(): int
    {
        return $this->limit;
    }

    public function getCurrent(): int
    {
        return $this->current;
    }

    public function getRetryAfter(): ?int
    {
        return $this->retryAfter;
    }

    public function getRemainingRequests(): int
    {
        return max(0, $this->limit - $this->current);
    }

    // ===== WAF Intelligence Methods =====

    /**
     * Check if request shows signs of attack
     */
    public function isAttackSuspected(): bool
    {
        return $this->threatScore?->getValue() >= 70.0 || ! empty($this->attackPatterns);
    }

    /**
     * Check if request shows baseline deviation
     */
    public function hasAnomalousTraffic(): bool
    {
        return $this->baselineDeviation !== null && abs($this->baselineDeviation) >= 3.0;
    }

    /**
     * Get threat level classification
     */
    public function getThreatLevel(): string
    {
        if ($this->threatScore === null) {
            return 'unknown';
        }

        $score = $this->threatScore->getValue();

        return match (true) {
            $score >= 90.0 => 'critical',
            $score >= 70.0 => 'high',
            $score >= 40.0 => 'medium',
            $score >= 20.0 => 'low',
            default => 'minimal'
        };
    }

    /**
     * Get recommended response strategy
     */
    public function getRecommendedStrategy(): array
    {
        $strategies = [];

        if ($this->isAttackSuspected()) {
            $strategies[] = 'immediate_block';
            $strategies[] = 'security_alert';
        }

        if ($this->hasAnomalousTraffic()) {
            $strategies[] = 'enhanced_monitoring';
            $strategies[] = 'adaptive_rate_limiting';
        }

        if (! empty($this->anomalyIndicators)) {
            $strategies[] = 'behavior_analysis';
        }

        return array_merge($strategies, $this->responseStrategies);
    }

    /**
     * Check if result warrants security event logging
     */
    public function shouldLogSecurityEvent(): bool
    {
        return $this->isAttackSuspected() ||
               $this->hasAnomalousTraffic() ||
               ! $this->isAllowed();
    }

    /**
     * Convert to comprehensive analysis array
     */
    public function toAnalysisArray(): array
    {
        return [
            'basic_result' => [
                'allowed' => $this->isAllowed(),
                'limit' => $this->getLimit(),
                'current' => $this->getCurrent(),
                'retry_after' => $this->getRetryAfter(),
                'remaining' => $this->getRemainingRequests(),
            ],
            'threat_analysis' => [
                'threat_score' => $this->threatScore?->getValue(),
                'threat_level' => $this->getThreatLevel(),
                'baseline_deviation' => $this->baselineDeviation,
                'attack_patterns' => $this->attackPatterns,
                'anomaly_indicators' => $this->anomalyIndicators,
                'confidence' => $this->confidence,
            ],
            'request_context' => [
                'client_ip' => $this->clientIp,
                'request_path' => $this->requestPath,
                'user_agent' => $this->userAgent,
                'analysis_timestamp' => $this->analysisTimestamp?->toIsoString(),
            ],
            'traffic_patterns' => [
                'traffic_analysis' => $this->trafficAnalysis,
                'burst_analysis' => $this->burstAnalysis,
                'geo_analysis' => $this->geoAnalysis,
            ],
            'response_guidance' => [
                'recommended_action' => $this->recommendedAction,
                'adaptive_retry_after' => $this->adaptiveRetryAfter?->toSeconds(),
                'response_strategies' => $this->getRecommendedStrategy(),
            ],
            'performance' => [
                'processing_time' => $this->processingTime?->toMilliseconds(),
                'performance_metrics' => $this->performanceMetrics,
            ],
        ];
    }
}
