using Microsoft.AspNetCore.Http;
namespace ClawdDotNet.Manager.Web;
///
/// Welche Instanz eine Anfrage meint.
///
/// Der Ordnername ist die Kennung. Er ist eindeutig — zwei Instanzen können
/// nicht im selben Verzeichnis liegen —, er ist stabil, und er ist lesbar. Die
/// Instanzkennung aus der Konfiguration wäre ebenfalls eindeutig, aber man müsste jede
/// Instanzdatei lesen, um von ihr auf ein Verzeichnis zu kommen; der Manager hat den Pfad
/// ohnehin in der Hand.
///
/// Und wenn nichts dabeisteht? Läuft genau eine Instanz, ist sie gemeint —
/// alles andere wäre Förmlichkeit gegenüber dem Normalfall. Laufen mehrere, wird
/// nachgefragt statt geraten: Eine Anfrage an die falsche Instanz ist schlimmer als eine
/// abgelehnte.
///
internal static class InstanceRouting
{
/// Die Kopfzeile, mit der die Weboberfläche die Instanz benennt.
public const string HeaderName = "X-Instanz";
public static string IdOf(ManagedInstance instance) => Path.GetFileName(instance.Directory);
/// Die gemeinte Instanz, oder eine Begründung, warum keine bestimmbar ist.
public static (ManagedInstance? Instance, string? Problem) Resolve(
InstanceRegistry registry, HttpContext context)
{
var alle = registry.Instances;
if (context.Request.Headers.TryGetValue(HeaderName, out var genannt)
&& !string.IsNullOrWhiteSpace(genannt))
{
var id = genannt.ToString().Trim();
var treffer = alle.FirstOrDefault(
i => string.Equals(IdOf(i), id, StringComparison.OrdinalIgnoreCase));
return treffer is null
? (null, $"Es gibt keine Instanz '{id}'.")
: (treffer, null);
}
var laufend = alle.Where(i => i.Condition == InstanceCondition.Running).ToList();
return laufend.Count switch
{
1 => (laufend[0], null),
0 => (null, "Es läuft keine Instanz."),
_ => (null, $"Es laufen {laufend.Count} Instanzen. "
+ $"Welche gemeint ist, gehört in die Kopfzeile {HeaderName}.")
};
}
}