// r8r: rust port of n8n.io
// Initial author: Michael Cochran <mcochran@cochranblock.org>
// Built for: Tanner Woodrum, intended cofounder
// License: Unlicense (public domain dedication, see UNLICENSE)
//
// `whatsapp_business` — send messages via the WhatsApp Cloud API
// (Meta Business Platform). Param names lifted from n8n source:
// operation, phoneNumberId, recipientPhoneNumber, messageType, textBody.
// Credential `whatsAppApi`: { accessToken }.

use async_trait::async_trait;
use crate::core::error::NodeError;
use crate::core::types::*;
use crate::engine::{ExecuteCtx, Node, NodeFactory};
use serde_json::{json, Value};
use std::sync::Arc;

pub struct WhatsAppBusinessNode;

static META: NodeMetadata = NodeMetadata {
    name: "whatsapp_business",
    display_name: "WhatsApp Business Cloud",
    version: &[1],
    group: &["output"],
    description: "Send WhatsApp messages via the Meta Cloud API",
    inputs: 1,
    outputs: 1,
    properties: &[
        PropertyDef { name: "operation", display_name: "Operation", kind: PropertyKind::Options, required: true, default: Some("send") },
        PropertyDef { name: "phoneNumberId", display_name: "Phone Number ID", kind: PropertyKind::String, required: true, default: None },
        PropertyDef { name: "recipientPhoneNumber", display_name: "Recipient Phone Number", kind: PropertyKind::String, required: true, default: None },
        PropertyDef { name: "messageType", display_name: "Message Type", kind: PropertyKind::Options, required: true, default: Some("text") },
        PropertyDef { name: "textBody", display_name: "Text Body", kind: PropertyKind::String, required: false, default: None },
    ],
    credentials: &[CredentialRef { name: "whatsAppApi", required: true }],
};

#[async_trait]
impl Node for WhatsAppBusinessNode {
    fn metadata(&self) -> &'static NodeMetadata { &META }

    async fn execute(&self, ctx: &mut ExecuteCtx<'_>) -> Result<NodeOutput, NodeError> {
        let token = ctx.credential_field("accessToken")?
            .as_str().ok_or_else(|| NodeError::MissingCredential("whatsAppApi.accessToken".into()))?
            .to_string();
        let base_url = ctx.credential_field("base_url").ok()
            .and_then(|v| v.as_str().map(|s| s.trim_end_matches('/').to_string()))
            .unwrap_or_else(|| "https://graph.facebook.com/v18.0".to_string());
        let phone_number_id = ctx.param_str("phoneNumberId")?;
        let to = ctx.param_str("recipientPhoneNumber")?;
        let message_type = ctx.param_opt_str("messageType").unwrap_or_else(|| "text".into());

        let mut body = json!({
            "messaging_product": "whatsapp",
            "to": to,
            "type": message_type,
        });
        match message_type.as_str() {
            "text" => {
                let text = ctx.param_str("textBody")?;
                body.as_object_mut().unwrap().insert("text".into(), json!({ "body": text }));
            }
            other => return Err(NodeError::Other(format!("whatsapp_business: messageType `{}` not implemented in v0.1", other))),
        }

        let resp = reqwest::Client::new()
            .post(format!("{}/{}/messages", base_url, phone_number_id))
            .bearer_auth(&token)
            .json(&body)
            .send().await.map_err(|e| NodeError::Http(format!("whatsapp_business: {}", e)))?;
        let status = resp.status();
        let parsed: Value = resp.json().await.unwrap_or(Value::Null);
        if !status.is_success() {
            return Err(NodeError::Http(format!("whatsapp_business {}: {}", status, parsed)));
        }
        Ok(vec![vec![NodeItem { json: parsed, ..Default::default() }]])
    }
}

inventory::submit! { NodeFactory::new("whatsapp_business", || Arc::new(WhatsAppBusinessNode)) }
