namespace ClaudeDo.Worker.Usage.TokenTracker;

/// <summary>One row of <c>tokentracker sessions --format json</c>. Field names mirror the
/// export's <c>snake_case</c> keys: <c>cached_input_tokens</c> is the cache *read* count,
/// <c>cache_creation_input_tokens</c> the write count.
/// ⚠️ <paramref name="SessionHash"/> is <b>not</b> unique across rows — TokenTracker splits one
/// Claude session into several rows (measured: 886 rows over 547 hashes), e.g. on a model switch.
/// The segments are disjoint, so summing rows that share a hash is correct; counting them is not
/// the same as counting sessions.</summary>
public sealed record TokenTrackerSession(
    string SessionHash,
    string Source,
    string Model,
    DateTimeOffset StartedAt,
    long InputTokens,
    long OutputTokens,
    long CacheReadTokens,
    long CacheCreationTokens,
    double CostUsd,
    int Turns,
    int RetryTurns,
    bool Productive,
    bool OneShot);

/// <summary>A parsed export plus when we fetched it. <paramref name="FormatVersion"/> is the
/// <c>version</c> field of the session rows — the only compatibility signal the export gives us.</summary>
public sealed record TokenTrackerExport(
    int FormatVersion,
    IReadOnlyList<TokenTrackerSession> Sessions,
    DateTime FetchedAtUtc);

public sealed record TokenTrackerProbe(
    bool Installed,
    string? Version,
    bool NodeOk,
    string? NodeVersion,
    string? Error)
{
    public static TokenTrackerProbe Unknown { get; } = new(false, null, false, null, null);
}

/// <summary>Where the local dashboard is reachable, or why it isn't. Same contract as
/// <see cref="TokenTrackerRunResult"/>: a failure is a value, never an exception.</summary>
public sealed record TokenTrackerDashboard(bool Ok, string? Url, string? Error);

/// <summary>Outcome of one CLI invocation. <paramref name="Ok"/> false always carries an
/// <paramref name="Error"/> — callers turn that into state, never into an exception.</summary>
public sealed record TokenTrackerRunResult(bool Ok, string StdOut, string? Error);

/// <summary>Aggregated per date/model/scope. <c>Scope</c> is <c>"claudedo"</c> or <c>"other"</c>,
/// decided by whether the session hash belongs to one of our runs. <c>Sessions</c> replaces the
/// old assistant-message count — it counts export <i>rows</i> (session segments), because the
/// export has neither message granularity nor one row per session.</summary>
public sealed record TokenTrackerModelRow(
    DateOnly Date,
    string Model,
    string Scope,
    long InputTokens,
    long OutputTokens,
    long CacheReadTokens,
    long CacheCreationTokens,
    int Sessions,
    double CostUsd);

/// <summary>What the export adds on top of what <c>task_runs</c> already knows about a task.</summary>
public sealed record TokenTrackerTaskExtras(
    double CostUsd,
    int Retries,
    bool Productive,
    bool OneShot);
