use serde::{Deserialize, Serialize};

/// Direction of a message in an ACP interaction replay.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum Direction {
    ClientToAgent,
    AgentToClient,
}

/// Source system that the replay was recorded from.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum ReplaySource {
    Zed,
    Claude,
    Custom(String),
}

/// A single message in an ACP replay sequence.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ReplayMessage {
    pub direction: Direction,
    pub payload: serde_json::Value,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub delay_ms: Option<u64>,
}

/// A complete ACP interaction replay containing a named sequence of messages.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AcpReplay {
    pub name: String,
    pub source: ReplaySource,
    pub messages: Vec<ReplayMessage>,
}

impl AcpReplay {
    /// Returns only the messages sent from client to agent.
    pub fn client_messages(&self) -> Vec<&ReplayMessage> {
        self.messages
            .iter()
            .filter(|m| m.direction == Direction::ClientToAgent)
            .collect()
    }

    /// Returns only the messages sent from agent to client.
    pub fn agent_messages(&self) -> Vec<&ReplayMessage> {
        self.messages
            .iter()
            .filter(|m| m.direction == Direction::AgentToClient)
            .collect()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::fixtures;

    #[test]
    fn test_load_minimal_fixture() {
        let replay = fixtures::load_fixture("minimal_init.json").unwrap();
        assert_eq!(replay.name, "minimal_init");
        assert_eq!(replay.messages.len(), 2);
    }

    #[test]
    fn test_filter_by_direction() {
        let replay = fixtures::load_fixture("minimal_init.json").unwrap();
        assert_eq!(replay.client_messages().len(), 1);
        assert_eq!(replay.agent_messages().len(), 1);
    }

    #[test]
    fn test_list_fixtures() {
        let fixtures = fixtures::list_fixtures();
        assert!(fixtures.contains(&"minimal_init.json".to_string()));
    }

    #[test]
    fn test_serde_roundtrip() {
        let replay = fixtures::load_fixture("minimal_init.json").unwrap();
        let json = serde_json::to_string_pretty(&replay).unwrap();
        let parsed: AcpReplay = serde_json::from_str(&json).unwrap();
        assert_eq!(parsed.name, replay.name);
        assert_eq!(parsed.messages.len(), replay.messages.len());
    }
}
