<?php

declare(strict_types=1);

namespace App\Framework\ErrorReporting\Analytics\ValueObjects;

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

/**
 * Represents a detected error anomaly with statistical significance
 */
final readonly class ErrorAnomaly
{
    public function __construct(
        public DateTimeImmutable $period,
        public int $count,
        public int $expected,
        public Score $zScore,
        public AnomalyType $type,
        public AnomalySeverity $severity
    ) {
    }

    public static function create(
        DateTimeImmutable $period,
        int $count,
        float $mean,
        float $zScore
    ): self {
        return new self(
            period: $period,
            count: $count,
            expected: (int) round($mean),
            zScore: Score::fromFloat($zScore),
            type: $count > $mean ? AnomalyType::SPIKE : AnomalyType::DROP,
            severity: $zScore > 3 ? AnomalySeverity::HIGH : AnomalySeverity::MEDIUM
        );
    }

    public function isSpike(): bool
    {
        return $this->type === AnomalyType::SPIKE;
    }

    public function isDrop(): bool
    {
        return $this->type === AnomalyType::DROP;
    }

    public function isHighSeverity(): bool
    {
        return $this->severity === AnomalySeverity::HIGH;
    }

    public function isStatisticallySignificant(): bool
    {
        return $this->zScore->value() > 2.5;
    }

    public function isCriticalAnomaly(): bool
    {
        return $this->zScore->value() > 3.0;
    }

    /**
     * @return array<string, mixed>
     */
    public function toArray(): array
    {
        return [
            'period' => $this->period->format('Y-m-d H:i:s'),
            'count' => $this->count,
            'expected' => $this->expected,
            'z_score' => $this->zScore->value(),
            'type' => $this->type->value,
            'severity' => $this->severity->value,
        ];
    }
}
