using MessagePack;

namespace ZB.MOM.WW.OtOpcUa.Driver.FOCAS.Shared.Contracts;

/// <summary>
///     Read one FOCAS address. Multi-read is the Proxy's responsibility — it batches
///     per-tag reads into parallel <see cref="ReadRequest"/> frames the Host services on its
///     STA thread. Keeping the IPC read single-address keeps the Host side trivial; FOCAS
///     itself has no multi-read primitive that spans area kinds.
/// </summary>
[MessagePackObject]
public sealed class ReadRequest
{
    [Key(0)] public long SessionId { get; set; }
    [Key(1)] public FocasAddressDto Address { get; set; } = new();
    [Key(2)] public int DataType { get; set; }
    [Key(3)] public int TimeoutMs { get; set; } = 2000;
}

[MessagePackObject]
public sealed class ReadResponse
{
    [Key(0)] public bool Success { get; set; }
    [Key(1)] public string? Error { get; set; }

    /// <summary>OPC UA status code mapped by the Host via <c>FocasStatusMapper</c> — 0 = Good.</summary>
    [Key(2)] public uint StatusCode { get; set; }

    /// <summary>MessagePack-serialized boxed value. <c>null</c> when <see cref="Success"/> is false.</summary>
    [Key(3)] public byte[]? ValueBytes { get; set; }

    /// <summary>Matches <see cref="FocasDataTypeCode"/> so the Proxy knows how to deserialize.</summary>
    [Key(4)] public int ValueTypeCode { get; set; }

    [Key(5)] public long SourceTimestampUtcUnixMs { get; set; }
}

[MessagePackObject]
public sealed class WriteRequest
{
    [Key(0)] public long SessionId { get; set; }
    [Key(1)] public FocasAddressDto Address { get; set; } = new();
    [Key(2)] public int DataType { get; set; }
    [Key(3)] public byte[]? ValueBytes { get; set; }
    [Key(4)] public int ValueTypeCode { get; set; }
    [Key(5)] public int TimeoutMs { get; set; } = 2000;
}

[MessagePackObject]
public sealed class WriteResponse
{
    [Key(0)] public bool Success { get; set; }
    [Key(1)] public string? Error { get; set; }

    /// <summary>OPC UA status code — 0 = Good.</summary>
    [Key(2)] public uint StatusCode { get; set; }
}

/// <summary>
///     PMC bit read-modify-write. Handled as a first-class operation (not two separate
///     read+write round-trips) so the critical section stays on the Host — serializing
///     concurrent bit writers to the same parent byte is Host-side via
///     <c>SemaphoreSlim</c> keyed on <c>(PmcLetter, Number)</c>. Mirrors the in-process
///     pattern from <c>FocasPmcBitRmw</c>.
/// </summary>
[MessagePackObject]
public sealed class PmcBitWriteRequest
{
    [Key(0)] public long SessionId { get; set; }
    [Key(1)] public FocasAddressDto Address { get; set; } = new();

    /// <summary>The bit index to set/clear. 0-7.</summary>
    [Key(2)] public int BitIndex { get; set; }

    [Key(3)] public bool Value { get; set; }
    [Key(4)] public int TimeoutMs { get; set; } = 2000;
}

[MessagePackObject]
public sealed class PmcBitWriteResponse
{
    [Key(0)] public bool Success { get; set; }
    [Key(1)] public string? Error { get; set; }
    [Key(2)] public uint StatusCode { get; set; }
}
