<?php

declare(strict_types=1);

namespace App\Framework\DDoS\Analysis\ValueObjects;

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

/**
 * Represents geographic distribution analysis for DDoS detection
 */
final readonly class GeographicDistribution
{
    public function __construct(
        public string $targetCountryCode,
        public int $totalRequests,
        public int $uniqueCountries,
        public Percentage $diversityPercentage,
        public Score $anomalyScore,
        public bool $isAnomalous,
        public DistributionPattern $pattern
    ) {
    }

    public static function analyze(
        string $countryCode,
        int $totalRequests,
        int $uniqueCountries,
        float $diversityThreshold = 0.8
    ): self {
        $diversityPercent = $totalRequests > 0 ? ($uniqueCountries / max($totalRequests, 1)) * 100 : 0;
        $diversityPercentage = Percentage::from(min(100, $diversityPercent));

        $isAnomalous = $diversityPercentage->getValue() >= ($diversityThreshold * 100);

        // Calculate anomaly score based on distribution patterns
        $anomalyScore = match (true) {
            $diversityPercentage->getValue() >= 90 => 0.9,
            $diversityPercentage->getValue() >= 80 => 0.7,
            $diversityPercentage->getValue() >= 60 => 0.5,
            $diversityPercentage->getValue() >= 40 => 0.3,
            default => 0.1
        };

        $pattern = match (true) {
            $diversityPercentage->getValue() >= 90 => DistributionPattern::GLOBAL_DISTRIBUTED,
            $diversityPercentage->getValue() >= 70 => DistributionPattern::HIGHLY_DISTRIBUTED,
            $diversityPercentage->getValue() >= 40 => DistributionPattern::MODERATELY_DISTRIBUTED,
            $diversityPercentage->getValue() >= 20 => DistributionPattern::REGIONALLY_CLUSTERED,
            default => DistributionPattern::SINGLE_ORIGIN
        };

        return new self(
            targetCountryCode: $countryCode,
            totalRequests: $totalRequests,
            uniqueCountries: $uniqueCountries,
            diversityPercentage: $diversityPercentage,
            anomalyScore: Score::fromFloat($anomalyScore),
            isAnomalous: $isAnomalous,
            pattern: $pattern
        );
    }

    public function indicatesDDoS(): bool
    {
        return $this->isAnomalous && $this->anomalyScore->value() >= 0.7;
    }

    public function isGlobalAttack(): bool
    {
        return $this->pattern === DistributionPattern::GLOBAL_DISTRIBUTED;
    }

    public function requiresImmedateAction(): bool
    {
        return $this->anomalyScore->value() >= 0.8 && $this->totalRequests >= 100;
    }

    /**
     * @return array<string, mixed>
     */
    public function toArray(): array
    {
        return [
            'target_country' => $this->targetCountryCode,
            'total_requests' => $this->totalRequests,
            'unique_countries' => $this->uniqueCountries,
            'diversity_percentage' => $this->diversityPercentage->getValue(),
            'anomaly_score' => $this->anomalyScore->value(),
            'is_anomalous' => $this->isAnomalous,
            'pattern' => $this->pattern->value,
        ];
    }
}
