<?php

declare(strict_types=1);

namespace App\Framework\Database\HealthCheck;

use App\Framework\Database\ConnectionInterface;

final class HealthCheckScheduler
{
    private array $healthChecks = [];

    private array $lastResults = [];

    public function __construct(
        private readonly ConnectionHealthChecker $healthChecker
    ) {
    }

    /**
     * Registriert einen Health Check
     */
    public function registerHealthCheck(
        string $name,
        ConnectionInterface $connection,
        int $intervalSeconds = 30,
        bool $detailed = false
    ): self {
        $this->healthChecks[$name] = [
            'connection' => $connection,
            'interval' => $intervalSeconds,
            'detailed' => $detailed,
            'last_check' => 0,
        ];

        return $this;
    }

    /**
     * Führt alle fälligen Health Checks aus
     */
    public function runScheduledChecks(): array
    {
        $results = [];
        $currentTime = time();

        foreach ($this->healthChecks as $name => $config) {
            if (($currentTime - $config['last_check']) >= $config['interval']) {
                $result = $this->runHealthCheck($name, $config);
                $results[$name] = $result;

                $this->lastResults[$name] = $result;
                $this->healthChecks[$name]['last_check'] = $currentTime;
            }
        }

        return $results;
    }

    /**
     * Führt einen spezifischen Health Check aus
     */
    public function runHealthCheck(string $name, ?array $config = null): HealthCheckResult
    {
        $config = $config ?? $this->healthChecks[$name] ?? null;

        if (! $config) {
            return HealthCheckResult::error(
                new \InvalidArgumentException("Health check '{$name}' not found")
            );
        }

        try {
            if ($config['detailed']) {
                return $this->healthChecker->checkDetailedHealth($config['connection']);
            } else {
                return $this->healthChecker->checkHealth($config['connection']);
            }
        } catch (\Throwable $e) {
            return HealthCheckResult::error($e);
        }
    }

    /**
     * Gibt alle letzten Health Check-Ergebnisse zurück
     */
    public function getAllResults(): array
    {
        return $this->lastResults;
    }

    /**
     * Gibt das letzte Ergebnis für einen spezifischen Health Check zurück
     */
    public function getLastResult(string $name): ?HealthCheckResult
    {
        return $this->lastResults[$name] ?? null;
    }

    /**
     * Prüft ob alle registrierten Connections gesund sind
     */
    public function areAllHealthy(): bool
    {
        foreach ($this->lastResults as $result) {
            if (! $result->isHealthy) {
                return false;
            }
        }

        return true;
    }

    /**
     * Gibt eine Zusammenfassung aller Health Checks zurück
     */
    public function getSummary(): array
    {
        $total = count($this->healthChecks);
        $healthy = 0;
        $unhealthy = 0;
        $unknown = 0;

        foreach ($this->healthChecks as $name => $config) {
            if (isset($this->lastResults[$name])) {
                if ($this->lastResults[$name]->isHealthy) {
                    $healthy++;
                } else {
                    $unhealthy++;
                }
            } else {
                $unknown++;
            }
        }

        return [
            'total_checks' => $total,
            'healthy' => $healthy,
            'unhealthy' => $unhealthy,
            'unknown' => $unknown,
            'overall_status' => $unhealthy === 0 ? 'healthy' : 'unhealthy',
            'last_updated' => time(),
        ];
    }

    /**
     * Entfernt einen Health Check
     */
    public function unregisterHealthCheck(string $name): self
    {
        unset($this->healthChecks[$name], $this->lastResults[$name]);

        return $this;
    }

    /**
     * Löscht alle Health Checks
     */
    public function clear(): self
    {
        $this->healthChecks = [];
        $this->lastResults = [];

        return $this;
    }
}
