//! Device management — register, list, and revoke devices.

use quicproquo_proto::bytes::Bytes;
use quicproquo_proto::prost::Message;
use quicproquo_proto::{method_ids, qpq::v1};
use quicproquo_rpc::client::RpcClient;

use crate::error::SdkError;

/// Info about a registered device.
pub struct DeviceInfo {
    pub device_id: Vec<u8>,
    pub device_name: String,
    pub registered_at: u64,
}

/// Register a device for multi-device support.
/// Returns `true` if the device was newly registered, `false` if it already existed.
pub async fn register_device(
    rpc: &RpcClient,
    device_id: &[u8],
    device_name: &str,
) -> Result<bool, SdkError> {
    let req = v1::RegisterDeviceRequest {
        device_id: device_id.to_vec(),
        device_name: device_name.to_string(),
    };
    let resp_bytes = rpc
        .call(method_ids::REGISTER_DEVICE, Bytes::from(req.encode_to_vec()))
        .await?;
    let resp = v1::RegisterDeviceResponse::decode(resp_bytes)
        .map_err(|e| SdkError::Other(anyhow::anyhow!("decode RegisterDeviceResponse: {e}")))?;
    Ok(resp.success)
}

/// List all registered devices for the authenticated identity.
pub async fn list_devices(
    rpc: &RpcClient,
) -> Result<Vec<DeviceInfo>, SdkError> {
    let req = v1::ListDevicesRequest {};
    let resp_bytes = rpc
        .call(method_ids::LIST_DEVICES, Bytes::from(req.encode_to_vec()))
        .await?;
    let resp = v1::ListDevicesResponse::decode(resp_bytes)
        .map_err(|e| SdkError::Other(anyhow::anyhow!("decode ListDevicesResponse: {e}")))?;
    let devices = resp
        .devices
        .into_iter()
        .map(|d| DeviceInfo {
            device_id: d.device_id,
            device_name: d.device_name,
            registered_at: d.registered_at,
        })
        .collect();
    Ok(devices)
}

/// Revoke (remove) a registered device.
/// Returns `true` if the device was found and revoked.
pub async fn revoke_device(
    rpc: &RpcClient,
    device_id: &[u8],
) -> Result<bool, SdkError> {
    let req = v1::RevokeDeviceRequest {
        device_id: device_id.to_vec(),
    };
    let resp_bytes = rpc
        .call(method_ids::REVOKE_DEVICE, Bytes::from(req.encode_to_vec()))
        .await?;
    let resp = v1::RevokeDeviceResponse::decode(resp_bytes)
        .map_err(|e| SdkError::Other(anyhow::anyhow!("decode RevokeDeviceResponse: {e}")))?;
    Ok(resp.success)
}
