//! Send message action for BlueBubbles

use crate::service::BlueBubblesService;
use async_trait::async_trait;
use elizaos::types::HandlerOptions;
use elizaos::{ActionDefinition, ActionHandler, ActionResult, Memory, State};
use std::sync::Arc;
use tracing::{error, info, warn};

/// Action to send a message via BlueBubbles/iMessage
pub struct SendMessageAction {
    service: Arc<BlueBubblesService>,
}

impl SendMessageAction {
    /// Creates a new send message action
    pub fn new(service: Arc<BlueBubblesService>) -> Self {
        Self { service }
    }
}

#[async_trait]
impl ActionHandler for SendMessageAction {
    fn definition(&self) -> ActionDefinition {
        ActionDefinition {
            name: "SEND_BLUEBUBBLES_MESSAGE".to_string(),
            description: "Send a message via iMessage through BlueBubbles".to_string(),
            similes: Some(vec![
                "SEND_IMESSAGE".to_string(),
                "TEXT_MESSAGE".to_string(),
                "IMESSAGE_REPLY".to_string(),
                "BLUEBUBBLES_SEND".to_string(),
                "APPLE_MESSAGE".to_string(),
            ]),
            examples: None,
            priority: None,
            tags: None,
            parameters: None,
        }
    }

    async fn validate(&self, _message: &Memory, _state: Option<&State>) -> bool {
        self.service.client().is_some()
    }

    async fn handle(
        &self,
        message: &Memory,
        state: Option<&State>,
        _options: Option<&HandlerOptions>,
    ) -> std::result::Result<Option<ActionResult>, anyhow::Error> {
        // Get channel_id (chat GUID) from state values, set by the provider
        let channel_id = state
            .and_then(|s| s.get_value("chatGuid"))
            .and_then(|v| v.as_str().map(String::from))
            .ok_or_else(|| anyhow::anyhow!("No chat GUID found in state"))?;

        let text = message
            .content
            .text
            .as_deref()
            .ok_or_else(|| anyhow::anyhow!("No message text"))?;

        if text.trim().is_empty() {
            warn!("Empty message text, skipping send");
            return Ok(None);
        }

        let reply_to = message.content.in_reply_to.as_deref();

        match self.service.send_message(&channel_id, text, reply_to).await {
            Ok(guid) => {
                info!("Sent BlueBubbles message: {}", guid);

                Ok(Some(
                    ActionResult::success(format!("Sent message: {}", guid))
                        .with_data("messageGuid", serde_json::json!(guid))
                        .with_data("chatGuid", serde_json::json!(channel_id)),
                ))
            }
            Err(e) => {
                error!("Failed to send BlueBubbles message: {}", e);
                Err(anyhow::anyhow!("Failed to send message: {}", e))
            }
        }
    }
}
