//! Market data subscription helpers for the cTrader Open API.
//!
//! Provides functions to subscribe/unsubscribe to spot price events.

use prost::Message;
use tracing::info;

use crate::dispatch::MessageDispatcher;
use crate::error::{CTraderError, Result};
use crate::proto::{self, ProtoMessage};

/// Subscribe to spot price events for the given symbol IDs.
pub async fn subscribe_spots(
    dispatcher: &MessageDispatcher,
    account_id: i64,
    symbol_ids: &[i64],
    timeout: std::time::Duration,
) -> Result<()> {
    info!(symbols = ?symbol_ids, "subscribing to spot events");

    let req = proto::ProtoOaSubscribeSpotsReq {
        payload_type: Some(proto::PT_SUBSCRIBE_SPOTS_REQ as i32),
        ctid_trader_account_id: account_id,
        symbol_id: symbol_ids.to_vec(),
        subscribe_to_spot_timestamp: Some(true),
    };

    let envelope = ProtoMessage {
        payload_type: proto::PT_SUBSCRIBE_SPOTS_REQ,
        payload: Some(req.encode_to_vec()),
        client_msg_id: None,
    };

    let resp = dispatcher.send_request(envelope, timeout).await?;

    if resp.payload_type != proto::PT_SUBSCRIBE_SPOTS_RES {
        return Err(CTraderError::ProtocolError(format!(
            "expected SubscribeSpotsRes ({}), got {}",
            proto::PT_SUBSCRIBE_SPOTS_RES,
            resp.payload_type
        )));
    }

    info!(count = symbol_ids.len(), "spot subscription confirmed");
    Ok(())
}

/// Unsubscribe from spot price events for the given symbol IDs.
pub async fn unsubscribe_spots(
    dispatcher: &MessageDispatcher,
    account_id: i64,
    symbol_ids: &[i64],
    timeout: std::time::Duration,
) -> Result<()> {
    info!(symbols = ?symbol_ids, "unsubscribing from spot events");

    let req = proto::ProtoOaUnsubscribeSpotsReq {
        payload_type: Some(proto::PT_UNSUBSCRIBE_SPOTS_REQ as i32),
        ctid_trader_account_id: account_id,
        symbol_id: symbol_ids.to_vec(),
    };

    let envelope = ProtoMessage {
        payload_type: proto::PT_UNSUBSCRIBE_SPOTS_REQ,
        payload: Some(req.encode_to_vec()),
        client_msg_id: None,
    };

    let resp = dispatcher.send_request(envelope, timeout).await?;

    if resp.payload_type != proto::PT_UNSUBSCRIBE_SPOTS_RES {
        return Err(CTraderError::ProtocolError(format!(
            "expected UnsubscribeSpotsRes ({}), got {}",
            proto::PT_UNSUBSCRIBE_SPOTS_RES,
            resp.payload_type
        )));
    }

    info!(count = symbol_ids.len(), "spot unsubscription confirmed");
    Ok(())
}
