//! Message handler trait and node handler types.

use crate::message::Context;
use crate::runtime::{NodeBase, Result};
use async_trait::async_trait;
use std::collections::HashMap;
use std::sync::Arc;
use tokio::sync::RwLock;

/// Message handler trait that all nodes must implement.
///
/// This trait defines the lifecycle methods for a node:
/// - `on_create`: Called when the node is created
/// - `on_message`: Called for each message the node receives
/// - `on_close`: Called when the node is destroyed
#[async_trait]
pub trait MessageHandler: Send + Sync + 'static {
    /// Called when the node is created.
    ///
    /// Use this to initialize resources, validate configuration, etc.
    async fn on_create(&mut self) -> Result<()>;

    /// Called for each message the node receives.
    ///
    /// This is the main processing method where you read inputs,
    /// perform operations, and set outputs.
    async fn on_message(&mut self, ctx: &mut Context) -> Result<()>;

    /// Called when the node is destroyed.
    ///
    /// Use this to clean up resources.
    async fn on_close(&mut self) -> Result<()>;
}

/// Node handler that wraps a MessageHandler with node metadata.
pub struct NodeHandler {
    pub node: NodeBase,
    pub handler: Arc<RwLock<Box<dyn MessageHandler>>>,
}

// Global handlers registry
lazy_static::lazy_static! {
    static ref HANDLERS: parking_lot::RwLock<HashMap<String, NodeHandler>> = parking_lot::RwLock::new(HashMap::new());
}

/// Add a node handler to the registry.
pub fn add_node_handler(node: NodeBase, handler: Box<dyn MessageHandler>) {
    let guid = node.guid.clone();
    let node_handler = NodeHandler {
        node,
        handler: Arc::new(RwLock::new(handler)),
    };
    HANDLERS.write().insert(guid, node_handler);
}

/// Get a node handler by GUID.
pub fn get_node_handler(guid: &str) -> Option<NodeHandlerRef> {
    let handlers = HANDLERS.read();
    handlers.get(guid).map(|h| NodeHandlerRef {
        node: h.node.clone(),
        handler: h.handler.clone(),
    })
}

/// Reference to a node handler for use outside the registry.
pub struct NodeHandlerRef {
    pub node: NodeBase,
    pub handler: Arc<RwLock<Box<dyn MessageHandler>>>,
}
