using System.Text.Json.Serialization;

namespace Flyshot.Core.Domain;

/// <summary>
/// Represents the current high-level controller state consumed by web monitoring and APIs.
/// </summary>
public sealed class ControllerStateSnapshot
{
    /// <summary>
    /// Initializes a controller state snapshot with safe default collections.
    /// </summary>
    public ControllerStateSnapshot(
        DateTimeOffset capturedAt,
        string connectionState,
        bool isEnabled,
        bool isInMotion,
        double speedRatio,
        IEnumerable<double>? jointPositions = null,
        IEnumerable<double>? cartesianPose = null,
        IEnumerable<RuntimeAlarm>? activeAlarms = null,
        IEnumerable<uint>? stateTailWords = null,
        byte? j519Status = null,
        uint? j519Sequence = null,
        bool? j519AcceptsCommand = null,
        bool? j519ReceivedCommand = null,
        bool? j519SystemReady = null,
        bool? j519RobotInMotion = null)
    {
        if (string.IsNullOrWhiteSpace(connectionState))
        {
            throw new ArgumentException("Connection state is required.", nameof(connectionState));
        }

        if (speedRatio < 0.0)
        {
            throw new ArgumentOutOfRangeException(nameof(speedRatio), "Speed ratio must be zero or positive.");
        }

        // Default to empty immutable snapshots so disconnected states still serialize safely.
        var copiedJointPositions = jointPositions?.ToArray() ?? Array.Empty<double>();
        var copiedCartesianPose = cartesianPose?.ToArray() ?? Array.Empty<double>();
        var copiedActiveAlarms = activeAlarms?.ToArray() ?? Array.Empty<RuntimeAlarm>();
        var copiedStateTailWords = stateTailWords?.ToArray() ?? Array.Empty<uint>();

        CapturedAt = capturedAt;
        ConnectionState = connectionState;
        IsEnabled = isEnabled;
        IsInMotion = isInMotion;
        SpeedRatio = speedRatio;
        JointPositions = copiedJointPositions;
        CartesianPose = copiedCartesianPose;
        ActiveAlarms = copiedActiveAlarms;
        StateTailWords = copiedStateTailWords;
        J519Status = j519Status;
        J519Sequence = j519Sequence;
        J519AcceptsCommand = j519AcceptsCommand;
        J519ReceivedCommand = j519ReceivedCommand;
        J519SystemReady = j519SystemReady;
        J519RobotInMotion = j519RobotInMotion;
    }

    /// <summary>
    /// Gets the capture time of the snapshot.
    /// </summary>
    [JsonPropertyName("capturedAt")]
    public DateTimeOffset CapturedAt { get; }

    /// <summary>
    /// Gets the high-level connection state label.
    /// </summary>
    [JsonPropertyName("connectionState")]
    public string ConnectionState { get; }

    /// <summary>
    /// Gets a value indicating whether the robot is enabled.
    /// </summary>
    [JsonPropertyName("isEnabled")]
    public bool IsEnabled { get; }

    /// <summary>
    /// Gets a value indicating whether the robot is currently moving.
    /// </summary>
    [JsonPropertyName("isInMotion")]
    public bool IsInMotion { get; }

    /// <summary>
    /// Gets the effective speed ratio reported by the controller.
    /// </summary>
    [JsonPropertyName("speedRatio")]
    public double SpeedRatio { get; }

    /// <summary>
    /// Gets the current joint positions when available.
    /// </summary>
    [JsonPropertyName("jointPositions")]
    public IReadOnlyList<double> JointPositions { get; }

    /// <summary>
    /// Gets the current Cartesian pose when available.
    /// </summary>
    [JsonPropertyName("cartesianPose")]
    public IReadOnlyList<double> CartesianPose { get; }

    /// <summary>
    /// Gets the active alarms visible at capture time.
    /// </summary>
    [JsonPropertyName("activeAlarms")]
    public IReadOnlyList<RuntimeAlarm> ActiveAlarms { get; }

    /// <summary>
    /// 获取 TCP 10010 状态帧尾部原始状态字，仅用于诊断，不直接推断运行语义。
    /// </summary>
    [JsonPropertyName("stateTailWords")]
    public IReadOnlyList<uint> StateTailWords { get; }

    /// <summary>
    /// 获取最近一次 UDP 60015 J519 响应的原始状态字节；没有响应时为 null。
    /// </summary>
    [JsonPropertyName("j519Status")]
    public byte? J519Status { get; }

    /// <summary>
    /// 获取最近一次 UDP 60015 J519 响应序号；没有响应时为 null。
    /// </summary>
    [JsonPropertyName("j519Sequence")]
    public uint? J519Sequence { get; }

    /// <summary>
    /// 获取 J519 accept_cmd 状态位；没有响应时为 null。
    /// </summary>
    [JsonPropertyName("j519AcceptsCommand")]
    public bool? J519AcceptsCommand { get; }

    /// <summary>
    /// 获取 J519 received_cmd 状态位；没有响应时为 null。
    /// </summary>
    [JsonPropertyName("j519ReceivedCommand")]
    public bool? J519ReceivedCommand { get; }

    /// <summary>
    /// 获取 J519 sysrdy 状态位；没有响应时为 null。
    /// </summary>
    [JsonPropertyName("j519SystemReady")]
    public bool? J519SystemReady { get; }

    /// <summary>
    /// 获取 J519 rbt_inmotion 状态位；没有响应时为 null。
    /// </summary>
    [JsonPropertyName("j519RobotInMotion")]
    public bool? J519RobotInMotion { get; }
}
