namespace ClawdDotNet.Core.Deploymentcenter.Watchdog;

/// <summary>
/// Die Statuswerte, die der Watchdog kennt. <c>stopped</c> und <c>maintenance</c> sind
/// angekündigte Zustände — der Evaluator lässt solche Monitore in Ruhe, statt wenige
/// Minuten nach einem geplanten Herunterfahren einen Fehlalarm zu erzeugen.
/// </summary>
public static class WatchdogStatus
{
    public const string Ok = "ok";
    public const string Warning = "warning";
    public const string Error = "error";
    public const string Stopped = "stopped";
    public const string Maintenance = "maintenance";
}

/// <summary>
/// Eine selbst ermittelte Teilprüfung. Das Deploymentcenter interpretiert den Namen
/// nicht — es liest nur <see cref="Ok"/> und <see cref="Message"/>. Was „gesund"
/// bedeutet, entscheidet damit jede Anwendung selbst.
///
/// <para>Schlägt eine Prüfung fehl, stuft der Server einen als <c>ok</c> gemeldeten
/// Heartbeat auf <c>warning</c> herab. Das ist der Unterschied zwischen „ein Faden
/// läuft" und „die Anwendung tut, was sie soll".</para>
/// </summary>
public sealed record HealthCheck(bool Ok, string? Message = null);

/// <summary>Momentaufnahme des Instanz-Zustands für einen Heartbeat.</summary>
/// <param name="Status">Einer der Werte aus <see cref="WatchdogStatus"/>.</param>
/// <param name="Message">Kurzbegründung, erscheint im Dashboard.</param>
/// <param name="Metrics">
/// Nur Zahlen: Das Deploymentcenter legt sie mit Zeitstempel ab (14 Tage) und vergleicht
/// den aktuellen Wert mit dem Sieben-Tage-Schnitt desselben Monitors. Nicht-numerische
/// Werte würden dabei stillschweigend verworfen — beschreibende Angaben gehören
/// deshalb in <paramref name="Message"/> oder in die Checks.
/// </param>
/// <param name="Checks">Selbst ermittelter Gesundheitszustand je Teilbereich.</param>
public sealed record InstanceHealth(
    string Status,
    string? Message,
    IReadOnlyDictionary<string, double> Metrics,
    IReadOnlyDictionary<string, HealthCheck> Checks)
{
    public static InstanceHealth Ok(string? message = null) => new(
        WatchdogStatus.Ok, message,
        new Dictionary<string, double>(),
        new Dictionary<string, HealthCheck>());
}

/// <summary>Liefert vor jedem Heartbeat den aktuellen Instanz-Zustand.</summary>
public interface IInstanceHealthProvider
{
    Task<InstanceHealth> GetAsync(CancellationToken ct);
}
