<?php

declare(strict_types=1);

namespace App\Framework\Process\ValueObjects\Logs;

/**
 * Ergebnis einer Log-Analyse.
 */
final readonly class LogAnalysisResult
{
    /**
     * @param LogEntry[] $entries
     * @param array<string, int> $levelCounts
     */
    public function __construct(
        public array $entries,
        public int $totalLines,
        public array $levelCounts,
        public \DateTimeImmutable $analyzedAt
    ) {
    }

    /**
     * Erstellt Ergebnis aus Log-Einträgen.
     *
     * @param LogEntry[] $entries
     */
    public static function fromEntries(array $entries, int $totalLines): self
    {
        $levelCounts = [];

        foreach ($entries as $entry) {
            $level = $entry->level;
            $levelCounts[$level] = ($levelCounts[$level] ?? 0) + 1;
        }

        return new self(
            entries: $entries,
            totalLines: $totalLines,
            levelCounts: $levelCounts,
            analyzedAt: new \DateTimeImmutable()
        );
    }

    /**
     * Gibt die Anzahl der Errors zurück.
     */
    public function getErrorCount(): int
    {
        return array_sum(array_map(
            fn ($level, $count) => in_array($level, ['ERROR', 'CRITICAL', 'ALERT', 'EMERGENCY'], true) ? $count : 0,
            array_keys($this->levelCounts),
            $this->levelCounts
        ));
    }

    /**
     * Gibt die Anzahl der Warnings zurück.
     */
    public function getWarningCount(): int
    {
        return $this->levelCounts['WARNING'] ?? 0;
    }

    /**
     * Gibt nur Error-Einträge zurück.
     *
     * @return LogEntry[]
     */
    public function getErrors(): array
    {
        return array_filter(
            $this->entries,
            fn (LogEntry $entry) => $entry->isError()
        );
    }

    /**
     * Gibt nur Warning-Einträge zurück.
     *
     * @return LogEntry[]
     */
    public function getWarnings(): array
    {
        return array_filter(
            $this->entries,
            fn (LogEntry $entry) => $entry->isWarning()
        );
    }

    /**
     * Gibt die häufigsten Fehler-Messages zurück.
     *
     * @return array<string, int>
     */
    public function getTopErrors(int $limit = 10): array
    {
        $messageCounts = [];

        foreach ($this->getErrors() as $entry) {
            $messageCounts[$entry->message] = ($messageCounts[$entry->message] ?? 0) + 1;
        }

        arsort($messageCounts);

        return array_slice($messageCounts, 0, $limit, true);
    }

    /**
     * Konvertiert zu Array.
     *
     * @return array<string, mixed>
     */
    public function toArray(): array
    {
        return [
            'total_lines' => $this->totalLines,
            'analyzed_entries' => count($this->entries),
            'level_counts' => $this->levelCounts,
            'error_count' => $this->getErrorCount(),
            'warning_count' => $this->getWarningCount(),
            'analyzed_at' => $this->analyzedAt->format('Y-m-d H:i:s'),
        ];
    }
}
