using ClaudeDo.Worker.Usage.TokenTracker;

namespace ClaudeDo.Worker.Tests.Usage.TokenTracker;

public sealed class TokenTrackerStateTests
{
    private static TokenTrackerExport Export(DateTime fetchedAt) =>
        new(11, [], fetchedAt);

    [Fact]
    public void FreshState_IsEmpty()
    {
        var state = new TokenTrackerState();

        Assert.Null(state.Export);
        Assert.Null(state.LastAttemptUtc);
        Assert.Null(state.LastError);
    }

    [Fact]
    public void ReportSuccess_StoresExportAndClearsError()
    {
        var state = new TokenTrackerState();
        var at = new DateTime(2026, 8, 24, 9, 0, 0, DateTimeKind.Utc);
        state.ReportFailure("boom", at.AddMinutes(-1));

        state.ReportSuccess(Export(at));

        Assert.NotNull(state.Export);
        Assert.Equal(at, state.LastAttemptUtc);
        Assert.Null(state.LastError);
    }

    [Fact]
    public void ReportFailure_KeepsPreviousExport()
    {
        var state = new TokenTrackerState();
        var good = new DateTime(2026, 8, 24, 9, 0, 0, DateTimeKind.Utc);
        state.ReportSuccess(Export(good));

        state.ReportFailure("tokentracker exited with code 1", good.AddMinutes(30));

        Assert.NotNull(state.Export);
        Assert.Equal(good, state.Export!.FetchedAtUtc);
        Assert.Equal("tokentracker exited with code 1", state.LastError);
        Assert.Equal(good.AddMinutes(30), state.LastAttemptUtc);
    }

    [Fact]
    public void IsOlderThan_NoExport_IsTrue()
    {
        Assert.True(new TokenTrackerState().IsOlderThan(TimeSpan.FromMinutes(15),
            new DateTime(2026, 8, 24, 9, 0, 0, DateTimeKind.Utc)));
    }

    [Fact]
    public void IsOlderThan_ComparesAgainstFetchTime()
    {
        var state = new TokenTrackerState();
        var fetched = new DateTime(2026, 8, 24, 9, 0, 0, DateTimeKind.Utc);
        state.ReportSuccess(Export(fetched));

        Assert.False(state.IsOlderThan(TimeSpan.FromMinutes(15), fetched.AddMinutes(14)));
        Assert.True(state.IsOlderThan(TimeSpan.FromMinutes(15), fetched.AddMinutes(16)));
    }
}
