//! availability — Query which time ranges have data for a datastream.
//!
//! # Examples
//!
//! ```no_run
//! # async fn example() -> ticksupply::Result<()> {
//! let client = ticksupply::Client::new()?;
//! let avail = client.availability().get(12345).await?;
//! for r in &avail.ranges {
//!     println!("{} - {}: ~{} rows", r.from_ns.as_i64(), r.to_ns.as_i64(), r.rows_estimate);
//! }
//! # Ok(()) }
//! ```

use serde::Deserialize;

use crate::client::Client;
use crate::error::Result;
use crate::http::{send, RequestOpts};
use crate::resources::catalog::DatastreamInfo;
use crate::timestamp::{Nanos, Timestamp};

/// A contiguous range of available data.
#[derive(Debug, Clone, Deserialize)]
pub struct AvailabilityRange {
    /// Inclusive start of the range.
    #[serde(rename = "from")]
    pub from_ns: Nanos,
    /// Exclusive end of the range.
    #[serde(rename = "to")]
    pub to_ns: Nanos,
    /// Server-estimated row count in the range.
    pub rows_estimate: u64,
}

/// Availability response — time ranges with stored data for a datastream.
#[derive(Debug, Clone, Deserialize)]
pub struct AvailabilityResponse {
    /// Identifying info for the queried datastream.
    pub datastream: DatastreamInfo,
    /// Time ranges with data.
    pub ranges: Vec<AvailabilityRange>,
    /// When availability data was last updated (RFC 3339 / ISO 8601).
    pub updated_at: Timestamp,
}

/// Accessor for `/availability`.
pub struct AvailabilityResource<'a> {
    pub(crate) client: &'a Client,
}

impl<'a> AvailabilityResource<'a> {
    /// Retrieves availability information for a datastream.
    ///
    /// The response describes which time ranges have data stored, along with
    /// per-range row estimates.
    ///
    /// # Errors
    ///
    /// - [`crate::Error::NotFound`] if no datastream has this identifier.
    /// - [`crate::Error::Authentication`] on invalid credentials.
    /// - [`crate::Error::Network`] on transport failure.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// # async fn example() -> ticksupply::Result<()> {
    /// let client = ticksupply::Client::new()?;
    /// let avail = client.availability().get(12345).await?;
    /// for r in &avail.ranges {
    ///     println!("{} -> {}", r.from_ns.as_i64(), r.to_ns.as_i64());
    /// }
    /// # Ok(()) }
    /// ```
    pub async fn get(&self, datastream_id: i64) -> Result<AvailabilityResponse> {
        let q = [("datastream_id", datastream_id.to_string())];
        send::<_, ()>(
            self.client,
            reqwest::Method::GET,
            "/availability",
            Some(&q[..]),
            None,
            RequestOpts::default(),
        )
        .await
    }
}
