using ZB.MOM.WW.HistorianGateway.Contracts.Grpc;

namespace ZB.MOM.WW.OtOpcUa.Driver.Historian.Gateway;

/// <summary>
/// Abstraction over the HistorianGateway gRPC client surface consumed by the OtOpcUa historian
/// backend driver. Proto-typed (the wire contract lives in
/// <c>ZB.MOM.WW.HistorianGateway.Contracts.Grpc</c>); the concrete adapter wrapping
/// <c>HistorianGatewayClient</c> is supplied by a later task. The seam exists so the driver and
/// its tests can depend on a fake without a live gateway.
/// </summary>
public interface IHistorianGatewayClient : IAsyncDisposable
{
    /// <summary>Streams raw historian samples for a tag over a time window.</summary>
    /// <param name="tag">The historian tag name to read.</param>
    /// <param name="startUtc">Inclusive start of the requested time window (UTC).</param>
    /// <param name="endUtc">Exclusive end of the requested time window (UTC).</param>
    /// <param name="maxValues">The maximum number of raw samples to return.</param>
    /// <param name="ct">Cancellation token.</param>
    /// <returns>An async stream of raw historian samples for the tag.</returns>
    IAsyncEnumerable<HistorianSample> ReadRawAsync(
        string tag,
        DateTime startUtc,
        DateTime endUtc,
        int maxValues,
        CancellationToken ct);

    /// <summary>Streams aggregate samples for a tag using the given retrieval mode and interval.</summary>
    /// <param name="tag">The historian tag name to read.</param>
    /// <param name="startUtc">Inclusive start of the requested time window (UTC).</param>
    /// <param name="endUtc">Exclusive end of the requested time window (UTC).</param>
    /// <param name="mode">The aggregate retrieval mode to apply.</param>
    /// <param name="interval">The aggregation bucket interval.</param>
    /// <param name="ct">Cancellation token.</param>
    /// <returns>An async stream of aggregate samples for the tag.</returns>
    IAsyncEnumerable<HistorianAggregateSample> ReadAggregateAsync(
        string tag,
        DateTime startUtc,
        DateTime endUtc,
        RetrievalMode mode,
        TimeSpan interval,
        CancellationToken ct);

    /// <summary>Reads the samples nearest to each of the requested timestamps (unary).</summary>
    /// <param name="tag">The historian tag name to read.</param>
    /// <param name="timestampsUtc">The timestamps (UTC) to find the nearest sample for.</param>
    /// <param name="ct">Cancellation token.</param>
    /// <returns>The samples nearest to each requested timestamp.</returns>
    Task<IReadOnlyList<HistorianSample>> ReadAtTimeAsync(
        string tag,
        IReadOnlyList<DateTime> timestampsUtc,
        CancellationToken ct);

    /// <summary>Streams historian events over a window, optionally filtered to a single source name.</summary>
    /// <param name="sourceName">Optional source-name filter; <c>null</c> returns events from all sources.</param>
    /// <param name="startUtc">Inclusive start of the time window (UTC).</param>
    /// <param name="endUtc">Exclusive end of the time window (UTC).</param>
    /// <param name="maxEvents">
    /// Caps the number of events returned. The gateway wire contract (<c>ReadEventsRequest</c>) has
    /// no per-call server cap, so this limit is enforced client-side by early stream termination:
    /// <c>0</c> or negative means no client-side limit (the gateway may still apply its configured
    /// <c>RuntimeDb:EventReadMaxRows</c>); a positive value stops draining after that many events.
    /// </param>
    /// <param name="ct">Cancellation token.</param>
    /// <returns>An async stream of historian events within the window.</returns>
    IAsyncEnumerable<HistorianEvent> ReadEventsAsync(
        string? sourceName,
        DateTime startUtc,
        DateTime endUtc,
        int maxEvents,
        CancellationToken ct);

    /// <summary>Writes live values for a tag through the gateway's SQL live-write path.</summary>
    /// <param name="tag">The historian tag name to write values for.</param>
    /// <param name="values">The live values to write.</param>
    /// <param name="ct">Cancellation token.</param>
    /// <returns>The write acknowledgement returned by the gateway.</returns>
    Task<WriteAck> WriteLiveValuesAsync(
        string tag,
        IReadOnlyList<HistorianLiveValue> values,
        CancellationToken ct);

    /// <summary>Sends a single historian event.</summary>
    /// <param name="evt">The historian event to send.</param>
    /// <param name="ct">Cancellation token.</param>
    /// <returns>The write acknowledgement returned by the gateway.</returns>
    Task<WriteAck> SendEventAsync(HistorianEvent evt, CancellationToken ct);

    /// <summary>Ensures the supplied tag definitions exist (create-or-update).</summary>
    /// <param name="definitions">The tag definitions to create or update.</param>
    /// <param name="ct">Cancellation token.</param>
    /// <returns>Per-tag outcomes for the create-or-update operation.</returns>
    Task<TagOperationResults> EnsureTagsAsync(
        IReadOnlyList<HistorianTagDefinition> definitions,
        CancellationToken ct);

    /// <summary>Probes gateway/historian reachability.</summary>
    /// <param name="ct">Cancellation token.</param>
    /// <returns><c>true</c> when the gateway and historian are reachable; otherwise <c>false</c>.</returns>
    Task<bool> ProbeAsync(CancellationToken ct);

    /// <summary>Reads the gateway's current historian connection status.</summary>
    /// <param name="ct">Cancellation token.</param>
    /// <returns>The current connection status reported by the gateway.</returns>
    Task<ConnectionStatus> GetConnectionStatusAsync(CancellationToken ct);
}
