<?php

declare(strict_types=1);

namespace App\Framework\Process\ValueObjects\Backup;

use App\Framework\Core\ValueObjects\Duration;

/**
 * Ergebnis einer Backup-Verifikation.
 */
final readonly class BackupVerificationResult
{
    /**
     * @param BackupFile[] $backups
     */
    public function __construct(
        public array $backups,
        public int $totalCount,
        public ?\DateTimeImmutable $latestBackupDate,
        public \DateTimeImmutable $verifiedAt
    ) {
    }

    /**
     * Erstellt Ergebnis aus Backup-Dateien.
     *
     * @param BackupFile[] $backups
     */
    public static function fromBackups(array $backups): self
    {
        $latestDate = null;

        foreach ($backups as $backup) {
            if ($latestDate === null || $backup->createdAt > $latestDate) {
                $latestDate = $backup->createdAt;
            }
        }

        return new self(
            backups: $backups,
            totalCount: count($backups),
            latestBackupDate: $latestDate,
            verifiedAt: new \DateTimeImmutable()
        );
    }

    /**
     * Prüft, ob es frische Backups gibt (< 24h).
     */
    public function hasFreshBackup(): bool
    {
        return $this->latestBackupDate !== null
            && ! $this->isLatestBackupOlderThan(Duration::fromDays(1));
    }

    /**
     * Prüft, ob das letzte Backup älter als X ist.
     */
    public function isLatestBackupOlderThan(Duration $duration): bool
    {
        if ($this->latestBackupDate === null) {
            return true;
        }

        $now = new \DateTimeImmutable();
        $diff = $now->getTimestamp() - $this->latestBackupDate->getTimestamp();

        return $diff > $duration->toSeconds();
    }

    /**
     * Gibt die Anzahl frischer Backups zurück.
     */
    public function getFreshBackupCount(): int
    {
        return count(array_filter(
            $this->backups,
            fn (BackupFile $backup) => $backup->isFresh()
        ));
    }

    /**
     * Gibt die Anzahl alter Backups zurück (> 7 Tage).
     */
    public function getOldBackupCount(): int
    {
        return count(array_filter(
            $this->backups,
            fn (BackupFile $backup) => $backup->isOlderThan(Duration::fromDays(7))
        ));
    }

    /**
     * Gibt das neueste Backup zurück.
     */
    public function getLatestBackup(): ?BackupFile
    {
        if (empty($this->backups)) {
            return null;
        }

        $latest = null;

        foreach ($this->backups as $backup) {
            if ($latest === null || $backup->createdAt > $latest->createdAt) {
                $latest = $backup;
            }
        }

        return $latest;
    }

    /**
     * Konvertiert zu Array.
     *
     * @return array<string, mixed>
     */
    public function toArray(): array
    {
        return [
            'total_count' => $this->totalCount,
            'fresh_count' => $this->getFreshBackupCount(),
            'old_count' => $this->getOldBackupCount(),
            'latest_backup_date' => $this->latestBackupDate?->format('Y-m-d H:i:s'),
            'has_fresh_backup' => $this->hasFreshBackup(),
            'verified_at' => $this->verifiedAt->format('Y-m-d H:i:s'),
            'backups' => array_map(fn (BackupFile $b) => $b->toArray(), $this->backups),
        ];
    }
}
