use serde::{Deserialize, Serialize};

/// Response from the /api/gen/{clip_id}/downbeats endpoint
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Downbeats {
    /// State of the downbeat detection: "running", "error", "complete", or "streaming"
    pub state: DownbeatsState,

    /// Error message if state is "error"
    #[serde(skip_serializing_if = "Option::is_none")]
    pub error_message: Option<String>,

    /// Whether this is the final result
    #[serde(skip_serializing_if = "Option::is_none")]
    pub r#final: Option<bool>,

    /// Processed downbeats: array of [time_in_seconds, beat_number] pairs
    /// beat_number is typically 1.0, 2.0, 3.0, 4.0 for 4/4 time signature
    #[serde(skip_serializing_if = "Option::is_none")]
    pub downbeats: Option<Vec<Vec<f64>>>,

    /// Onset times in seconds
    #[serde(skip_serializing_if = "Option::is_none")]
    pub onsets: Option<Vec<f64>>,

    /// Raw onset times before processing
    #[serde(skip_serializing_if = "Option::is_none")]
    pub raw_onsets: Option<Vec<f64>>,

    /// Raw downbeats from onset detection: array of [time_in_seconds, beat_number] pairs
    #[serde(skip_serializing_if = "Option::is_none")]
    pub raw_onset_downbeats: Option<Vec<Vec<f64>>>,

    /// Raw downbeats before refinement: array of [time_in_seconds, beat_number] pairs
    #[serde(skip_serializing_if = "Option::is_none")]
    pub raw_downbeats: Option<Vec<Vec<f64>>>,

    /// How many seconds are missing from the start of the audio for alignment
    #[serde(skip_serializing_if = "Option::is_none")]
    pub seconds_missing_from_start: Option<f64>,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum DownbeatsState {
    Running,
    Error,
    Complete,
    Streaming,
}
