use crate::ir::NodeId;
use serde::{Deserialize, Serialize};
use serde_json::Value;

/// Platform-agnostic patch operations for updating the UI
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "camelCase")]
pub enum Patch {
    /// Create a new node
    Create {
        id: String,
        element_type: String,
        props: indexmap::IndexMap<String, Value>,
    },

    /// Set a property on an existing node
    SetProp {
        id: String,
        name: String,
        value: Value,
    },

    /// Set text content of a node
    SetText {
        id: String,
        text: String,
    },

    /// Insert a node into the tree
    Insert {
        parent_id: String,
        id: String,
        before_id: Option<String>,
    },

    /// Move a node to a new position
    Move {
        parent_id: String,
        id: String,
        before_id: Option<String>,
    },

    /// Remove a node from the tree
    Remove {
        id: String,
    },

    // Event handling is now done at the renderer level
}

impl Patch {
    pub fn create(id: NodeId, element_type: String, props: indexmap::IndexMap<String, Value>) -> Self {
        Self::Create {
            id: format!("{:?}", id),
            element_type,
            props,
        }
    }

    pub fn set_prop(id: NodeId, name: String, value: Value) -> Self {
        Self::SetProp {
            id: format!("{:?}", id),
            name,
            value,
        }
    }

    pub fn set_text(id: NodeId, text: String) -> Self {
        Self::SetText {
            id: format!("{:?}", id),
            text,
        }
    }

    pub fn insert(parent_id: NodeId, id: NodeId, before_id: Option<NodeId>) -> Self {
        Self::Insert {
            parent_id: format!("{:?}", parent_id),
            id: format!("{:?}", id),
            before_id: before_id.map(|id| format!("{:?}", id)),
        }
    }

    /// Insert a root node into the "root" container
    pub fn insert_root(id: NodeId) -> Self {
        Self::Insert {
            parent_id: "root".to_string(),
            id: format!("{:?}", id),
            before_id: None,
        }
    }

    pub fn move_node(parent_id: NodeId, id: NodeId, before_id: Option<NodeId>) -> Self {
        Self::Move {
            parent_id: format!("{:?}", parent_id),
            id: format!("{:?}", id),
            before_id: before_id.map(|id| format!("{:?}", id)),
        }
    }

    pub fn remove(id: NodeId) -> Self {
        Self::Remove {
            id: format!("{:?}", id),
        }
    }

    // Event handling methods removed - now done at renderer level
}
