/// Python event handler wrapper for Rust event system
use pyo3::prelude::*;
use pyo3::types::{PyDict, PyList};
use lumina_engine::{Event, EventHandler, EventType, EventError};
use async_trait::async_trait;

/// Python event handler that wraps a Python callable
pub struct PythonEventHandler {
    py_handler: PyObject,
    interested_types: Vec<EventType>,
}

impl PythonEventHandler {
    pub fn new(py_handler: PyObject, interested_types: Vec<EventType>) -> Self {
        Self {
            py_handler,
            interested_types,
        }
    }
}

#[async_trait]
impl EventHandler for PythonEventHandler {
    async fn handle(&self, event: &Event) -> Result<Vec<Event>, EventError> {
        // Parse event payload as JSON value (outside of Python::with_gil)
        let payload_value = &event.payload;
        
        Python::with_gil(|py| -> PyResult<Vec<Event>> {
            // Convert Event to Python dict with proper structure
            let event_dict = PyDict::new(py);
            
            // Set event_type as string
            let event_type_str = format!("{:?}", event.event_type);
            event_dict.set_item("event_type", event_type_str)?;
            
            // Set source
            event_dict.set_item("source", &event.source)?;
            
            // Convert payload JSON to Python dict
            let payload_dict = PyDict::new(py);
            if let serde_json::Value::Object(map) = payload_value {
                for (k, v) in map {
                    let py_value: PyObject = match v {
                        serde_json::Value::String(s) => s.to_object(py),
                        serde_json::Value::Number(n) => {
                            if n.is_i64() {
                                n.as_i64().unwrap().to_object(py)
                            } else if n.is_u64() {
                                n.as_u64().unwrap().to_object(py)
                            } else {
                                n.as_f64().unwrap().to_object(py)
                            }
                        }
                        serde_json::Value::Bool(b) => b.to_object(py),
                        serde_json::Value::Null => py.None(),
                        serde_json::Value::Array(arr) => {
                            // Convert array to Python list
                            let py_list = PyList::empty(py);
                            for item in arr {
                                let item_obj: PyObject = match item {
                                    serde_json::Value::String(s) => s.to_object(py),
                                    serde_json::Value::Number(n) => {
                                        if n.is_i64() {
                                            n.as_i64().unwrap().to_object(py)
                                        } else if n.is_u64() {
                                            n.as_u64().unwrap().to_object(py)
                                        } else {
                                            n.as_f64().unwrap().to_object(py)
                                        }
                                    }
                                    serde_json::Value::Bool(b) => b.to_object(py),
                                    serde_json::Value::Null => py.None(),
                                    _ => item.to_string().to_object(py),
                                };
                                py_list.append(item_obj)?;
                            }
                            py_list.to_object(py)
                        }
                        serde_json::Value::Object(_) => {
                            // For nested objects, convert to JSON string
                            serde_json::to_string(v).unwrap_or_default().to_object(py)
                        }
                    };
                    payload_dict.set_item(k, py_value)?;
                }
            }
            
            event_dict.set_item("payload", payload_dict)?;
            
            // Set other event fields
            event_dict.set_item("id", event.id.to_string())?;
            event_dict.set_item("timestamp", event.timestamp.to_rfc3339())?;
            
            // Call Python handler with the properly structured dict
            let result = self.py_handler.call1(py, (event_dict,))?;
            
            // Handler can return None or a list of new events
            if result.is_none(py) {
                Ok(Vec::new())
            } else {
                // For now, return empty vector
                // In full implementation, parse returned events
                Ok(Vec::new())
            }
        })
        .map_err(|e: PyErr| EventError::HandlerError(format!("Python handler error: {}", e)))
    }
    
    fn interested_events(&self) -> Vec<EventType> {
        self.interested_types.clone()
    }
}

