using ZB.MOM.WW.LmxProxy.Client.Domain;

namespace ZB.MOM.WW.LmxProxy.Client;

/// <summary>
/// Interface for LmxProxy client operations.
/// </summary>
public interface ILmxProxyClient : IDisposable, IAsyncDisposable
{
    /// <summary>Gets or sets the default timeout for operations (range: 1s to 10min).</summary>
    TimeSpan DefaultTimeout { get; set; }

    /// <summary>Connects to the LmxProxy service and establishes a session.</summary>
    Task ConnectAsync(CancellationToken cancellationToken = default);

    /// <summary>Disconnects from the LmxProxy service.</summary>
    Task DisconnectAsync();

    /// <summary>Returns true if the client has an active session.</summary>
    Task<bool> IsConnectedAsync();

    /// <summary>Reads a single tag value.</summary>
    Task<Vtq> ReadAsync(string address, CancellationToken cancellationToken = default);

    /// <summary>Reads multiple tag values in a single batch.</summary>
    Task<IDictionary<string, Vtq>> ReadBatchAsync(IEnumerable<string> addresses, CancellationToken cancellationToken = default);

    /// <summary>Writes a single tag value (native TypedValue -- no string heuristics).</summary>
    Task WriteAsync(string address, TypedValue value, CancellationToken cancellationToken = default);

    /// <summary>Writes multiple tag values in a single batch.</summary>
    Task WriteBatchAsync(IDictionary<string, TypedValue> values, CancellationToken cancellationToken = default);

    /// <summary>
    /// Writes a batch of values, then polls a flag tag until it matches or timeout expires.
    /// Returns (writeResults, flagReached, elapsedMs).
    /// </summary>
    Task<WriteBatchAndWaitResponse> WriteBatchAndWaitAsync(
        IDictionary<string, TypedValue> values,
        string flagTag,
        TypedValue flagValue,
        int timeoutMs = 5000,
        int pollIntervalMs = 100,
        CancellationToken cancellationToken = default);

    /// <summary>Subscribes to tag updates with value and error callbacks.</summary>
    Task<LmxProxyClient.ISubscription> SubscribeAsync(
        IEnumerable<string> addresses,
        Action<string, Vtq> onUpdate,
        Action<Exception>? onStreamError = null,
        CancellationToken cancellationToken = default);

    /// <summary>Validates an API key and returns info.</summary>
    Task<LmxProxyClient.ApiKeyInfo> CheckApiKeyAsync(string apiKey, CancellationToken cancellationToken = default);

    /// <summary>Returns a snapshot of client-side metrics.</summary>
    Dictionary<string, object> GetMetrics();
}
