using System.Threading.Channels;
using Jiaowu.Api.Domain.System;

namespace Jiaowu.Api.Infrastructure.BackgroundJobs;

public sealed record BackgroundJobEnvelope(
    Guid OutboxMessageId,
    BackgroundJobKind JobKind,
    Guid JobId);

public interface IBackgroundJobTransport
{
    bool IsDurable { get; }

    ValueTask PublishAsync(
        BackgroundJobEnvelope message,
        CancellationToken cancellationToken);

    Task<bool> CheckHealthAsync(CancellationToken cancellationToken);
}

public sealed class InMemoryBackgroundJobTransport : IBackgroundJobTransport
{
    private readonly IReadOnlyDictionary<
        BackgroundJobKind,
        Channel<BackgroundJobEnvelope>> _channels =
        Enum.GetValues<BackgroundJobKind>().ToDictionary(
            kind => kind,
            _ => Channel.CreateBounded<BackgroundJobEnvelope>(
                new BoundedChannelOptions(256)
                {
                    FullMode = BoundedChannelFullMode.Wait,
                    SingleReader = false,
                    SingleWriter = false
                }));

    public bool IsDurable => false;

    public ValueTask PublishAsync(
        BackgroundJobEnvelope message,
        CancellationToken cancellationToken) =>
        _channels[message.JobKind].Writer.WriteAsync(message, cancellationToken);

    public Task<bool> CheckHealthAsync(CancellationToken cancellationToken) =>
        Task.FromResult(true);

    public IAsyncEnumerable<BackgroundJobEnvelope> ReadAllAsync(
        BackgroundJobKind kind,
        CancellationToken cancellationToken) =>
        _channels[kind].Reader.ReadAllAsync(cancellationToken);
}
