using ZB.MOM.WW.MxGateway.Client;
using ZB.MOM.WW.MxGateway.Contracts.Proto;
using ZB.MOM.WW.MxGateway.Contracts.Proto.Galaxy;

namespace ZB.MOM.WW.MxGateway.Client.Cli;

internal sealed class MxGatewayCliClientAdapter : IMxGatewayCliClient
{
    private readonly MxGatewayClient _client;
    private readonly Lazy<GalaxyRepositoryClient> _galaxyClient;

    /// <summary>
    /// Initializes a new instance of the <see cref="MxGatewayCliClientAdapter"/> that bridges the CLI to the gateway client.
    /// </summary>
    /// <param name="client">The gateway client to adapt.</param>
    public MxGatewayCliClientAdapter(MxGatewayClient client)
    {
        _client = client;
        _galaxyClient = new Lazy<GalaxyRepositoryClient>(
            () => GalaxyRepositoryClient.Create(_client.Options));
    }

    /// <inheritdoc />
    public Task<OpenSessionReply> OpenSessionAsync(
        OpenSessionRequest request,
        CancellationToken cancellationToken)
    {
        return _client.OpenSessionRawAsync(request, cancellationToken);
    }

    /// <inheritdoc />
    public Task<CloseSessionReply> CloseSessionAsync(
        CloseSessionRequest request,
        CancellationToken cancellationToken)
    {
        return _client.CloseSessionRawAsync(request, cancellationToken);
    }

    /// <inheritdoc />
    public Task<MxCommandReply> InvokeAsync(
        MxCommandRequest request,
        CancellationToken cancellationToken)
    {
        return _client.InvokeAsync(request, cancellationToken);
    }

    /// <inheritdoc />
    public IAsyncEnumerable<MxEvent> StreamEventsAsync(
        StreamEventsRequest request,
        CancellationToken cancellationToken)
    {
        return _client.StreamEventsAsync(request, cancellationToken);
    }

    /// <inheritdoc />
    public Task<AcknowledgeAlarmReply> AcknowledgeAlarmAsync(
        AcknowledgeAlarmRequest request,
        CancellationToken cancellationToken)
    {
        return _client.AcknowledgeAlarmAsync(request, cancellationToken);
    }

    /// <inheritdoc />
    public IAsyncEnumerable<AlarmFeedMessage> StreamAlarmsAsync(
        StreamAlarmsRequest request,
        CancellationToken cancellationToken)
    {
        return _client.StreamAlarmsAsync(request, cancellationToken);
    }

    /// <inheritdoc />
    public Task<TestConnectionReply> GalaxyTestConnectionAsync(
        TestConnectionRequest request,
        CancellationToken cancellationToken)
    {
        return _galaxyClient.Value.TestConnectionRawAsync(request, cancellationToken);
    }

    /// <inheritdoc />
    public Task<GetLastDeployTimeReply> GalaxyGetLastDeployTimeAsync(
        GetLastDeployTimeRequest request,
        CancellationToken cancellationToken)
    {
        return _galaxyClient.Value.GetLastDeployTimeRawAsync(request, cancellationToken);
    }

    /// <inheritdoc />
    public Task<DiscoverHierarchyReply> GalaxyDiscoverHierarchyAsync(
        DiscoverHierarchyRequest request,
        CancellationToken cancellationToken)
    {
        return _galaxyClient.Value.DiscoverHierarchyRawAsync(request, cancellationToken);
    }

    /// <inheritdoc />
    public IAsyncEnumerable<DeployEvent> GalaxyWatchDeployEventsAsync(
        WatchDeployEventsRequest request,
        CancellationToken cancellationToken)
    {
        return _galaxyClient.Value.WatchDeployEventsRawAsync(request, cancellationToken);
    }

    /// <inheritdoc />
    public Task<BrowseChildrenReply> GalaxyBrowseChildrenAsync(
        BrowseChildrenRequest request,
        CancellationToken cancellationToken)
    {
        return _galaxyClient.Value.BrowseChildrenRawAsync(request, cancellationToken);
    }

    /// <summary>Disposes the adapted gateway client and, if created, the lazily-initialized Galaxy Repository client.</summary>
    /// <returns>A task that represents the asynchronous operation.</returns>
    public async ValueTask DisposeAsync()
    {
        if (_galaxyClient.IsValueCreated)
        {
            await _galaxyClient.Value.DisposeAsync().ConfigureAwait(false);
        }

        await _client.DisposeAsync().ConfigureAwait(false);
    }
}
