using System.Collections.Concurrent;
using System.Collections.Generic;
namespace Gott.Services;
///
/// Out-of-band-Kanal für "Steering"-Einwürfe: Nachrichten, die der User schickt
/// WÄHREND eine Chain läuft (vgl. /btw bzw. Queued-Steering in Claude Code).
/// 1:1 gespiegelt vom – keyed by sessionId.
///
/// Der Streaming-Loop (AnthropicService.StreamChat) draint die Queue an den
/// Iterations-Grenzen (nach einer Tool-Runde bzw. bevor die Chain finalisiert)
/// und injiziert die Texte als User-Message in die laufende Konversation.
/// Ein laufender messages.create-Request ist unveränderlich – Injektion geht
/// nur ZWISCHEN den API-Calls, nicht mitten im Stream.
///
/// Im CLI-Pfad (AnthropicService.StreamChatViaCli) läuft der Agentic-Loop im
/// claude-Child; dort draint ein Kill-and-Restart am nächsten Tool-Boundary
/// (Child killen, Verlauf + Einwurf an den Prompt hängen, CLI neu starten).
///
public class SteeringQueue
{
private readonly ConcurrentDictionary> _queues = new ConcurrentDictionary>();
/// Reiht einen Einwurf für eine Session ein (FIFO).
public void Enqueue(string sessionId, string text)
{
if (string.IsNullOrEmpty(sessionId) || string.IsNullOrWhiteSpace(text)) return;
var q = _queues.GetOrAdd(sessionId, _ => new ConcurrentQueue());
q.Enqueue(text);
}
///
/// Entnimmt ALLE pending Einwürfe einer Session (FIFO) und gibt sie zurück.
/// Leere Liste wenn nichts ansteht.
///
public List Drain(string sessionId)
{
var result = new List();
if (_queues.TryGetValue(sessionId, out var q))
{
while (q.TryDequeue(out var text))
result.Add(text);
}
return result;
}
/// Prüft ob für eine Session Einwürfe anstehen.
public bool HasPending(string sessionId)
=> _queues.TryGetValue(sessionId, out var q) && !q.IsEmpty;
/// Entfernt die Queue einer Session (beim Chain-Ende aufräumen).
public void Clear(string sessionId) => _queues.TryRemove(sessionId, out _);
}