using System.Text.Json.Serialization;

namespace Mbproxy.Admin;

// ── Wire DTOs for the connection-detail debug view ───────────────────────────
// Pushed over SignalR to subscribers of a single PLC's detail page. camelCase via
// JsonKnownNamingPolicy.CamelCase on the source-gen context below.

/// <summary>
/// Per-PLC payload pushed to detail-page subscribers: the standard per-PLC status
/// row plus the real-time debug view's tag-value table. <see cref="Plc"/> is
/// <c>null</c> when the detail page is open for a PLC that is no longer in the
/// configuration (removed by a hot-reload) — the page renders a "no longer
/// configured" state.
/// </summary>
public sealed record PlcDetailResponse(
    PlcStatus? Plc,
    PlcDebugSnapshot Debug);

/// <summary>
/// Snapshot of one PLC's tag-value capture. <see cref="CaptureArmed"/> is <c>false</c>
/// when no detail page has armed the capture (e.g. a snapshot taken in the gap before
/// the SignalR subscription completes); the table is still returned so the view can
/// render one row per configured BCD tag.
/// </summary>
public sealed record PlcDebugSnapshot(
    bool CaptureArmed,
    IReadOnlyList<TagValueDto> Tags);

/// <summary>
/// One configured BCD tag's last observed value. <see cref="HasValue"/> is <c>false</c>
/// before any traffic has been captured for the tag since the capture was armed — the
/// view renders such rows as "no traffic yet".
/// </summary>
public sealed record TagValueDto(
    int Address,
    int Width,
    bool HasValue,
    /// <summary><c>"read"</c> (FC03/FC04) or <c>"write"</c> (FC06/FC16).</summary>
    string Direction,
    /// <summary>
    /// Raw PLC-side value as BCD nibbles in hex — <c>0xLLLL</c> for a 16-bit tag,
    /// <c>0xHHHHLLLL</c> (high word, low word) for a 32-bit tag. <c>"—"</c> when
    /// <see cref="HasValue"/> is false.
    /// </summary>
    string RawHex,
    /// <summary>Decoded binary integer the upstream client reads / wrote.</summary>
    long DecodedValue,
    /// <summary>ISO-8601 UTC time of the observation; <c>null</c> when no traffic yet.</summary>
    string? UpdatedAtUtc,
    /// <summary>Seconds since the observation; <c>null</c> when no traffic yet.</summary>
    double? AgeSeconds);

// ── Source-generation context ─────────────────────────────────────────────────

[JsonSerializable(typeof(PlcDetailResponse))]
[JsonSerializable(typeof(PlcDebugSnapshot))]
[JsonSourceGenerationOptions(
    WriteIndented = false,
    PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase)]
internal partial class DebugJsonContext : JsonSerializerContext;
