<?php

declare(strict_types=1);

namespace App\Framework\Monitoring;

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

/**
 * System-wide health summary value object
 */
final readonly class SystemHealthSummary
{
    public function __construct(
        public Timestamp $timestamp,
        public int $totalComponents,
        public int $healthyComponents,
        public int $degradedComponents,
        public int $failedComponents,
        public Percentage $overallHealthScore,
        public int $circuitBreakerCount,
        public int $errorBoundaryCount,
    ) {
    }

    /**
     * Get overall system status
     */
    public function getSystemStatus(): string
    {
        if ($this->failedComponents > 0) {
            $failureRate = $this->failedComponents / $this->totalComponents;

            if ($failureRate >= 0.5) {
                return 'critical';
            }

            if ($failureRate >= 0.25) {
                return 'major_issues';
            }

            return 'minor_issues';
        }

        if ($this->degradedComponents > 0) {
            $degradedRate = $this->degradedComponents / $this->totalComponents;

            if ($degradedRate >= 0.25) {
                return 'degraded';
            }

            return 'mostly_healthy';
        }

        return 'healthy';
    }

    /**
     * Get health percentage for healthy components
     */
    public function getHealthyPercentage(): Percentage
    {
        if ($this->totalComponents === 0) {
            return Percentage::fromFloat(0.0);
        }

        return Percentage::fromFloat($this->healthyComponents / $this->totalComponents);
    }

    /**
     * Get degraded percentage
     */
    public function getDegradedPercentage(): Percentage
    {
        if ($this->totalComponents === 0) {
            return Percentage::fromFloat(0.0);
        }

        return Percentage::fromFloat($this->degradedComponents / $this->totalComponents);
    }

    /**
     * Get failed percentage
     */
    public function getFailedPercentage(): Percentage
    {
        if ($this->totalComponents === 0) {
            return Percentage::fromFloat(0.0);
        }

        return Percentage::fromFloat($this->failedComponents / $this->totalComponents);
    }

    /**
     * Check if system is fully operational
     */
    public function isFullyOperational(): bool
    {
        return $this->failedComponents === 0 && $this->degradedComponents === 0;
    }

    /**
     * Check if system has critical issues
     */
    public function hasCriticalIssues(): bool
    {
        return $this->getSystemStatus() === 'critical';
    }

    /**
     * Get severity level (0-4: healthy, mostly_healthy, degraded, minor_issues, major_issues, critical)
     */
    public function getSeverityLevel(): int
    {
        return match ($this->getSystemStatus()) {
            'healthy' => 0,
            'mostly_healthy' => 1,
            'degraded' => 2,
            'minor_issues' => 3,
            'major_issues' => 4,
            'critical' => 5,
            default => 0,
        };
    }

    /**
     * Get summary statistics
     */
    public function getStatistics(): array
    {
        return [
            'timestamp' => $this->timestamp->toIsoString(),
            'system_status' => $this->getSystemStatus(),
            'severity_level' => $this->getSeverityLevel(),
            'is_fully_operational' => $this->isFullyOperational(),
            'has_critical_issues' => $this->hasCriticalIssues(),
            'components' => [
                'total' => $this->totalComponents,
                'healthy' => $this->healthyComponents,
                'degraded' => $this->degradedComponents,
                'failed' => $this->failedComponents,
            ],
            'percentages' => [
                'healthy' => $this->getHealthyPercentage()->toFloat(),
                'degraded' => $this->getDegradedPercentage()->toFloat(),
                'failed' => $this->getFailedPercentage()->toFloat(),
            ],
            'overall_health_score' => $this->overallHealthScore->toFloat(),
            'component_breakdown' => [
                'circuit_breakers' => $this->circuitBreakerCount,
                'error_boundaries' => $this->errorBoundaryCount,
            ],
        ];
    }

    /**
     * Convert to array for serialization
     */
    public function toArray(): array
    {
        return $this->getStatistics();
    }

    /**
     * Create from array
     */
    public static function fromArray(array $data): self
    {
        return new self(
            timestamp: Timestamp::fromFloat(strtotime($data['timestamp'])),
            totalComponents: $data['components']['total'],
            healthyComponents: $data['components']['healthy'],
            degradedComponents: $data['components']['degraded'],
            failedComponents: $data['components']['failed'],
            overallHealthScore: Percentage::fromFloat($data['overall_health_score']),
            circuitBreakerCount: $data['component_breakdown']['circuit_breakers'],
            errorBoundaryCount: $data['component_breakdown']['error_boundaries'],
        );
    }
}
