//! Claude Code JSON protocol types for stdin communication.
//!
//! When using `--input-format=stream-json`, Claude Code expects
//! newline-delimited JSON messages on stdin.

use serde::Serialize;

/// Message sent to Claude Code via stdin.
///
/// Format based on Claude Code's stream-json input protocol.
#[derive(Debug, Clone, Serialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum ClaudeInputMessage {
    /// A user message to send to Claude.
    User { message: UserMessage },
}

/// The inner user message structure.
#[derive(Debug, Clone, Serialize)]
pub struct UserMessage {
    /// Always "user" for user messages.
    pub role: String,
    /// The message content.
    pub content: String,
}

impl ClaudeInputMessage {
    /// Create a new user message.
    pub fn user(content: impl Into<String>) -> Self {
        Self::User {
            message: UserMessage {
                role: "user".to_string(),
                content: content.into(),
            },
        }
    }

    /// Serialize to a JSON string with trailing newline (NDJSON format).
    pub fn to_json_line(&self) -> Result<String, serde_json::Error> {
        let mut json = serde_json::to_string(self)?;
        json.push('\n');
        Ok(json)
    }
}

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

    #[test]
    fn test_user_message_serialization() {
        let msg = ClaudeInputMessage::user("Hello, Claude!");
        let json = msg.to_json_line().unwrap();

        // Should produce: {"type":"user","message":{"role":"user","content":"Hello, Claude!"}}\n
        assert!(json.starts_with(r#"{"type":"user","message":{"role":"user","content":"Hello, Claude!"}}"#));
        assert!(json.ends_with('\n'));
    }
}
