using NATS.Server.JetStream.Models;

namespace NATS.Server.JetStream.Api;

public sealed class JetStreamApiResponse
{
    public JetStreamApiError? Error { get; init; }
    public JetStreamStreamInfo? StreamInfo { get; init; }
    public JetStreamConsumerInfo? ConsumerInfo { get; init; }
    public JetStreamAccountInfo? AccountInfo { get; init; }
    public IReadOnlyList<string>? StreamNames { get; init; }
    public IReadOnlyList<string>? ConsumerNames { get; init; }
    public JetStreamStreamMessage? StreamMessage { get; init; }
    public JetStreamDirectMessage? DirectMessage { get; init; }
    public JetStreamSnapshot? Snapshot { get; init; }
    public JetStreamPullBatch? PullBatch { get; init; }
    public bool Success { get; init; }
    public ulong Purged { get; init; }

    public static JetStreamApiResponse NotFound(string subject) => new()
    {
        Error = new JetStreamApiError
        {
            Code = 404,
            Description = $"unknown api subject '{subject}'",
        },
    };

    public static JetStreamApiResponse Ok() => new();

    public static JetStreamApiResponse SuccessResponse() => new()
    {
        Success = true,
    };

    public static JetStreamApiResponse ErrorResponse(int code, string description) => new()
    {
        Error = new JetStreamApiError
        {
            Code = code,
            Description = description,
        },
    };

    /// <summary>
    /// Returns a not-leader error with code 10003 and a leader_hint.
    /// Go reference: jetstream_api.go:200-300 — non-leader nodes return this error
    /// for mutating operations so clients can redirect.
    /// </summary>
    public static JetStreamApiResponse NotLeader(string leaderHint) => new()
    {
        Error = new JetStreamApiError
        {
            Code = 10003,
            Description = "not leader",
            LeaderHint = leaderHint,
        },
    };

    /// <summary>
    /// Returns a purge success response with the number of messages purged.
    /// Go reference: jetstream_api.go:1200-1350 — purge response includes purged count.
    /// </summary>
    public static JetStreamApiResponse PurgeResponse(ulong purged) => new()
    {
        Success = true,
        Purged = purged,
    };
}

public sealed class JetStreamStreamInfo
{
    public required StreamConfig Config { get; init; }
    public required ApiStreamState State { get; init; }
}

public sealed class JetStreamConsumerInfo
{
    public required ConsumerConfig Config { get; init; }
}

public sealed class JetStreamAccountInfo
{
    public int Streams { get; init; }
    public int Consumers { get; init; }
}

public sealed class JetStreamStreamMessage
{
    public ulong Sequence { get; init; }
    public string Subject { get; init; } = string.Empty;
    public string Payload { get; init; } = string.Empty;
}

public sealed class JetStreamDirectMessage
{
    public ulong Sequence { get; init; }
    public string Subject { get; init; } = string.Empty;
    public string Payload { get; init; } = string.Empty;
}

public sealed class JetStreamSnapshot
{
    public string Payload { get; init; } = string.Empty;
}

public sealed class JetStreamPullBatch
{
    public IReadOnlyList<JetStreamDirectMessage> Messages { get; init; } = [];
}
