<?php

declare(strict_types=1);

namespace App\Framework\Waf\BotProtection\ValueObjects;

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

/**
 * Result of bot protection analysis
 */
final readonly class BotDetectionResult
{
    public function __construct(
        public bool $isBot,
        public BotRiskScore $riskScore,
        public array $detections,
        public Duration $processingTime,
        public ?Percentage $confidence = null,
        public ?BrowserFingerprint $fingerprint = null,
        public ?DeviceProfile $deviceProfile = null,
        public bool $captchaRequired = false,
        public bool $captchaValid = false,
        public array $riskFactors = [],
        public ?string $error = null
    ) {
    }

    /**
     * Get confidence with default fallback
     */
    public function getConfidence(): Percentage
    {
        return $this->confidence ?? Percentage::from(0.0);
    }

    /**
     * Create disabled result
     */
    public static function disabled(): self
    {
        return new self(
            isBot: false,
            riskScore: BotRiskScore::zero(),
            detections: [],
            processingTime: Duration::zero(),
            confidence: Percentage::from(0.0)
        );
    }

    /**
     * Create error result
     */
    public static function error(string $error, Duration $processingTime): self
    {
        return new self(
            isBot: false,
            riskScore: BotRiskScore::zero(),
            detections: [],
            processingTime: $processingTime,
            confidence: Percentage::from(0.0),
            error: $error
        );
    }

    /**
     * Check if request should be blocked
     */
    public function shouldBlock(): bool
    {
        return $this->isBot && $this->riskScore->getValue() >= 90.0;
    }

    /**
     * Check if request should be flagged
     */
    public function shouldFlag(): bool
    {
        return $this->isBot || $this->riskScore->getValue() >= 50.0;
    }

    /**
     * Check if request requires additional verification
     */
    public function requiresVerification(): bool
    {
        return $this->captchaRequired && ! $this->captchaValid;
    }

    /**
     * Get risk level description
     */
    public function getRiskLevel(): string
    {
        $score = $this->riskScore->getValue();

        return match (true) {
            $score >= 90.0 => 'CRITICAL',
            $score >= 75.0 => 'HIGH',
            $score >= 50.0 => 'MEDIUM',
            $score >= 25.0 => 'LOW',
            default => 'MINIMAL'
        };
    }

    /**
     * Get detection types present
     */
    public function getDetectionTypes(): array
    {
        $types = [];

        foreach ($this->detections as $detection) {
            if ($detection instanceof BotDetection) {
                $types[] = $detection->type->value;
            }
        }

        return array_unique($types);
    }

    /**
     * Get high-confidence detections
     */
    public function getHighConfidenceDetections(): array
    {
        return array_filter(
            $this->detections,
            fn ($detection) => $detection instanceof BotDetection && $detection->confidence->getValue() >= 80.0
        );
    }

    /**
     * Check if analysis had errors
     */
    public function hasError(): bool
    {
        return $this->error !== null;
    }

    /**
     * Convert to array for serialization
     */
    public function toArray(): array
    {
        return [
            'is_bot' => $this->isBot,
            'risk_score' => $this->riskScore->getValue(),
            'risk_level' => $this->getRiskLevel(),
            'detection_count' => count($this->detections),
            'detection_types' => $this->getDetectionTypes(),
            'captcha_required' => $this->captchaRequired,
            'captcha_valid' => $this->captchaValid,
            'should_block' => $this->shouldBlock(),
            'should_flag' => $this->shouldFlag(),
            'requires_verification' => $this->requiresVerification(),
            'confidence' => $this->getConfidence()->getValue(),
            'processing_time_ms' => $this->processingTime->toMilliseconds(),
            'risk_factors' => $this->riskFactors,
            'fingerprint' => $this->fingerprint?->toArray(),
            'device_profile' => $this->deviceProfile?->toArray(),
            'detections' => array_map(
                fn ($detection) => $detection instanceof BotDetection ? $detection->toArray() : $detection,
                $this->detections
            ),
            'error' => $this->error,
        ];
    }
}
