namespace Mbproxy.Proxy;

/// <summary>
/// Direction of a Modbus PDU being processed by the pipeline.
/// </summary>
public enum MbapDirection
{
    /// <summary>A request frame travelling from an upstream client to the backend PLC.</summary>
    RequestToBackend,

    /// <summary>A response frame travelling from the backend PLC back to the upstream client.</summary>
    ResponseToClient,
}

/// <summary>
/// Per-pair context carried through each PDU pipeline call. Carries only
/// <see cref="PlcName"/> at the base level; <see cref="PerPlcContext"/> extends it with
/// the BcdTagMap, counters, logger, and per-call <c>CurrentRequest</c> slot for
/// multiplexer-aware response correlation.
/// </summary>
public class PduContext
{
    /// <summary>The configured PLC name (from <c>MbproxyOptions.Plcs[i].Name</c>).</summary>
    public string PlcName { get; init; } = "";
}

/// <summary>
/// Hook contract for inspecting and rewriting Modbus PDU bytes inline.
/// Called once per frame in each direction (request and response).
///
/// Implementations must be safe to call concurrently from multiple connection pairs.
/// Production wires <see cref="BcdPduPipeline"/>; <see cref="NoopPduPipeline"/> is a
/// pass-through fallback used by tests.
/// </summary>
public interface IPduPipeline
{
    /// <summary>
    /// Processes a single Modbus PDU. Implementations may mutate <paramref name="pdu"/> in place.
    /// </summary>
    /// <param name="direction">Whether this is a request or a response frame.</param>
    /// <param name="mbapHeader">The 7-byte MBAP header (read-only; includes TxId, UnitId, FC is in pdu[0]).</param>
    /// <param name="pdu">The PDU bytes starting at the function code. May be mutated in place.</param>
    /// <param name="context">Per-pair context (PLC name; extended via <see cref="PerPlcContext"/>).</param>
    void Process(MbapDirection direction, ReadOnlySpan<byte> mbapHeader, Span<byte> pdu, PduContext context);
}
