use crate::common::{deserialize_thing_keys, serialize_thing_keys, RequiredValues};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;

/// Top-level POST body for a `deviceAlarm` request.
#[derive(Debug, Serialize, Deserialize)]
pub struct DeviceAlarmRequest {
    #[serde(rename = "deviceAlarm")]
    pub device_alarm: DeviceAlarmCommand,
}

impl DeviceAlarmRequest {
    /// Request all alarm fields for the given devices.
    pub fn new(thing_keys: Vec<String>) -> Self {
        Self {
            device_alarm: DeviceAlarmCommand {
                command: "deviceAlarm".to_owned(),
                params: DeviceAlarmParams {
                    thing_keys,
                    required_values: RequiredValues::All,
                },
            },
        }
    }
}

#[derive(Debug, Serialize, Deserialize)]
pub struct DeviceAlarmCommand {
    pub command: String,
    pub params: DeviceAlarmParams,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct DeviceAlarmParams {
    #[serde(
        rename = "thingKey",
        serialize_with = "serialize_thing_keys",
        deserialize_with = "deserialize_thing_keys"
    )]
    pub thing_keys: Vec<String>,
    #[serde(rename = "requiredValues")]
    pub required_values: RequiredValues,
}

/// Top-level response body for a `deviceAlarm` request.
#[derive(Debug, Serialize, Deserialize)]
pub struct DeviceAlarmResponse {
    #[serde(rename = "deviceAlarm")]
    pub device_alarm: DeviceAlarmResult,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct DeviceAlarmResult {
    pub params: DeviceAlarmResultParams,
    pub success: bool,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct DeviceAlarmResultParams {
    /// One entry per requested device. Each map has a single key: the device's `thingKey`.
    pub value: Vec<HashMap<String, DeviceAlarmData>>,
}

/// Alarm status for a single device.
#[derive(Debug, Default, Serialize, Deserialize)]
pub struct DeviceAlarmData {
    /// Active alarm IDs. An empty list means no active alarms.
    #[serde(rename = "deviceAlarm", skip_serializing_if = "Option::is_none")]
    pub device_alarm: Option<Vec<u32>>,
    /// ISO 8601 timestamp of the last received packet.
    #[serde(rename = "lastUpdate", skip_serializing_if = "Option::is_none")]
    pub last_update: Option<String>,
}
