namespace Mbproxy.Proxy.Multiplexing;

/// <summary>
/// One upstream party interested in a single backend round-trip. Carries the upstream
/// pipe to deliver the response to AND the original MBAP TxId that the party sent — the
/// multiplexer must rewrite the response's MBAP TxId back to <see cref="OriginalTxId"/>
/// before handing the frame to the pipe, so each upstream sees the proxy as transparent.
///
/// <para>Read coalescing fans out a single backend response to multiple upstream parties
/// via this record. Do not collapse this into a single field on
/// <see cref="InFlightRequest"/>.</para>
/// </summary>
internal sealed record InterestedParty(UpstreamPipe Pipe, ushort OriginalTxId);

/// <summary>
/// Per-backend-request correlation record. Stored in <see cref="CorrelationMap"/> keyed
/// by the proxy-assigned TxId; looked up by the backend reader task to:
/// <list type="bullet">
///   <item><description>Restore each interested party's original MBAP TxId before forwarding
///         the response upstream (transparent multiplexing contract).</description></item>
///   <item><description>Provide the BCD rewriter with the originating request's
///         <c>StartAddress</c> / <c>Qty</c> for FC03/FC04 response decoding — the response
///         PDU itself does not carry the start address.</description></item>
///   <item><description>Measure backend round-trip time via <see cref="SentAtUtc"/>.</description></item>
/// </list>
///
/// <para>The <see cref="InterestedParties"/> list shape is the load-bearing seam that
/// read coalescing uses to fan out a single PLC response to multiple upstream clients.
/// Reviewer note: do <i>not</i> simplify back to a single <c>UpstreamPipe</c> field.</para>
/// </summary>
/// <param name="IsHeartbeat">
/// <c>true</c> for the synthetic FC03 keepalive probe issued by the backend heartbeat
/// loop. Heartbeat entries carry no <see cref="InterestedParties"/>: the backend reader
/// drops the response (no fan-out, no rewriter, no cache) and the timeout watchdog tears
/// the backend down instead of dispatching a 0x0B exception. Defaults to <c>false</c>.
/// </param>
internal sealed record InFlightRequest(
    byte UnitId,
    byte Fc,
    ushort StartAddress,
    ushort Qty,
    IReadOnlyList<InterestedParty> InterestedParties,
    DateTimeOffset SentAtUtc,
    int ResolvedCacheTtlMs = 0,
    bool IsHeartbeat = false);
