using ClawdDotNet.Core.Config;

namespace ClawdDotNet.Core.Engine;

public sealed class LoopGuard
{
    private readonly LoopGuardConfig _cfg;
    private int _steps;
    private int _tokens;

    public LoopGuard(LoopGuardConfig cfg) => _cfg = cfg;

    public int Steps => _steps;
    public int Tokens => _tokens;

    public void RecordStep()
    {
        if (Interlocked.Increment(ref _steps) > _cfg.MaxSteps)
            throw new LoopLimitExceededException(
                $"Schritt-Limit erreicht: {_cfg.MaxSteps} Schritte pro Run.");
    }

    /// <summary>
    /// Bucht die abgerechneten Tokens eines Schritts auf das Kostenbudget des Runs.
    /// Das ist eine reine Kostenbremse — die Kontextgröße wird davon getrennt über
    /// <see cref="LoopGuardConfig.MaxContextTokens"/> und die Compaction gesteuert.
    /// </summary>
    public void RecordTokens(int count)
    {
        var total = Interlocked.Add(ref _tokens, count);
        if (total > _cfg.MaxCumulativeTokens)
            throw new LoopLimitExceededException(
                $"Kostenbudget erschöpft: {total:N0} von maximal {_cfg.MaxCumulativeTokens:N0} " +
                "abgerechneten Tokens in diesem Run. Hinweis: Jeder Schritt sendet den " +
                "kompletten Kontext erneut, die Summe wächst daher überproportional.");
    }
}

public sealed class LoopLimitExceededException(string message) : Exception(message);
