<?php

declare(strict_types=1);

namespace PpPhp\Core\Diagnostics\Results;

use PpPhp\Core\Diagnostics\Severity;

final class DiagnosticReport
{
    /** @var DiagnosticResult[] */
    private array $results = [];

    public function add(DiagnosticResult $result): void
    {
        $this->results[] = $result;
    }

    /** @return DiagnosticResult[] */
    public function results(): array
    {
        return $this->results;
    }

    public function countSeverity(string $severity): int
    {
        return array_sum(array_map(
            static fn (DiagnosticResult $result): int => $result->countBySeverity($severity),
            $this->results
        ));
    }

    public function criticalCount(): int
    {
        return $this->countSeverity(Severity::CRITICAL);
    }

    public function errorCount(): int
    {
        return $this->countSeverity(Severity::ERROR);
    }

    public function warningCount(): int
    {
        return $this->countSeverity(Severity::WARNING);
    }

    public function infoCount(): int
    {
        return $this->countSeverity(Severity::INFO);
    }

    public function totalIssues(): int
    {
        return array_sum(array_map(
            static fn (DiagnosticResult $result): int => count($result->issues()),
            $this->results
        ));
    }

    public function healthScore(): int
    {
        $penalty = array_sum(array_map(
            static fn (DiagnosticResult $result): int => $result->penalty(),
            $this->results
        ));

        return max(0, min(100, 100 - $penalty));
    }

    public function categorySummary(): array
    {
        $summary = [];

        foreach ($this->results as $result) {
            $category = $result->category();

            if (!isset($summary[$category])) {
                $summary[$category] = [
                    'critical' => 0,
                    'error' => 0,
                    'warning' => 0,
                    'info' => 0,
                    'score' => 100,
                ];
            }

            $summary[$category]['critical'] += $result->countBySeverity(Severity::CRITICAL);
            $summary[$category]['error'] += $result->countBySeverity(Severity::ERROR);
            $summary[$category]['warning'] += $result->countBySeverity(Severity::WARNING);
            $summary[$category]['info'] += $result->countBySeverity(Severity::INFO);
            $summary[$category]['score'] = max(0, 100 - (
                ($summary[$category]['critical'] * 20) +
                ($summary[$category]['error'] * 10) +
                ($summary[$category]['warning'] * 1)
            ));
        }

        return $summary;
    }

    public function toArray(): array
    {
        return [
            'healthScore' => $this->healthScore(),
            'critical' => $this->criticalCount(),
            'errors' => $this->errorCount(),
            'warnings' => $this->warningCount(),
            'info' => $this->infoCount(),
            'totalIssues' => $this->totalIssues(),
            'categories' => $this->categorySummary(),
            'results' => array_map(
                static fn (DiagnosticResult $result): array => $result->toArray(),
                $this->results
            ),
        ];
    }
}
