//! Windows backend — Win32/WinUI.
//!
//! Architecture: correct and complete. Win32/WinUI calls are stubs marked TODO.
//!
//! Each `PlatformNode` maps to a HWND or WinUI control:
//!   element("div")    → Panel (WinUI StackPanel)
//!   element("button") → Button (WinUI)
//!   element("input")  → TextBox (WinUI)
//!   text("...")       → TextBlock (WinUI)

use crate::{EventHandler, PlatformBackend, PlatformError, PlatformNode, PlatformResult};

pub struct WindowsBackend;

impl WindowsBackend {
    pub fn new() -> Self {
        Self
    }

    fn winui_control(tag: &str) -> &'static str {
        match tag {
            "button" => "Microsoft.UI.Xaml.Controls.Button",
            "input" => "Microsoft.UI.Xaml.Controls.TextBox",
            "textarea" => "Microsoft.UI.Xaml.Controls.TextBox",
            "img" => "Microsoft.UI.Xaml.Controls.Image",
            "ul" | "ol" => "Microsoft.UI.Xaml.Controls.ListView",
            "li" => "Microsoft.UI.Xaml.Controls.ListViewItem",
            "nav" => "Microsoft.UI.Xaml.Controls.NavigationView",
            _ => "Microsoft.UI.Xaml.Controls.StackPanel",
        }
    }

    fn winui_event(event: &str) -> &'static str {
        match event {
            "click" => "Click",
            "input" | "change" => "TextChanged",
            "focus" => "GotFocus",
            "blur" => "LostFocus",
            "keydown" | "keypress" => "KeyDown",
            "keyup" => "KeyUp",
            _ => "PointerPressed",
        }
    }
}

impl Default for WindowsBackend {
    fn default() -> Self {
        Self::new()
    }
}

impl PlatformBackend for WindowsBackend {
    fn name(&self) -> &'static str {
        "windows"
    }

    fn create_element(&self, tag: &str) -> PlatformResult<PlatformNode> {
        let mut node = PlatformNode::element(tag);
        // TODO: WinRT/COM activation via windows-rs crate:
        //   let panel: StackPanel = StackPanel::new()?;
        node.attributes
            .push(crate::Attribute::new("data-winui-control", Self::winui_control(tag)));
        Ok(node)
    }

    fn create_text(&self, content: &str) -> PlatformResult<PlatformNode> {
        let mut node = PlatformNode::text(content);
        // TODO: TextBlock::new()?.set_text(content)
        node.attributes
            .push(crate::Attribute::new("data-winui-control", "Microsoft.UI.Xaml.Controls.TextBlock"));
        Ok(node)
    }

    fn set_attribute(
        &self,
        node: &mut PlatformNode,
        name: &str,
        value: &str,
    ) -> PlatformResult<()> {
        // TODO: map to WinUI property setters
        node.attributes.retain(|a| a.name != name);
        node.attributes.push(crate::Attribute::new(name, value));
        Ok(())
    }

    fn remove_attribute(&self, node: &mut PlatformNode, name: &str) -> PlatformResult<()> {
        node.attributes.retain(|a| a.name != name);
        Ok(())
    }

    fn append_child(
        &self,
        parent: &mut PlatformNode,
        child: PlatformNode,
    ) -> PlatformResult<()> {
        // TODO: panel.Children().Append(child_element)
        parent.children.push(child);
        Ok(())
    }

    fn remove_child(&self, parent: &mut PlatformNode, child_index: usize) -> PlatformResult<()> {
        if child_index >= parent.children.len() {
            return Err(PlatformError::Render(format!(
                "windows: child index {} out of bounds",
                child_index
            )));
        }
        // TODO: panel.Children().RemoveAt(child_index)
        parent.children.remove(child_index);
        Ok(())
    }

    fn replace_child(
        &self,
        parent: &mut PlatformNode,
        index: usize,
        new_child: PlatformNode,
    ) -> PlatformResult<()> {
        if index >= parent.children.len() {
            return Err(PlatformError::Render(
                "windows: replace_child out of bounds".into(),
            ));
        }
        parent.children[index] = new_child;
        Ok(())
    }

    fn bind_event(
        &self,
        node: &mut PlatformNode,
        event: &str,
        _handler: EventHandler,
    ) -> PlatformResult<()> {
        let winui_event = Self::winui_event(event);
        // TODO: button.Click(TypedEventHandler::new(|sender, args| { handler(...) }))
        node.attributes.push(crate::Attribute::new(
            format!("data-winui-event-{}", event),
            winui_event,
        ));
        Ok(())
    }

    fn render_to_string(&self, node: &PlatformNode) -> PlatformResult<String> {
        Ok(node.to_html())
    }

    fn mount(&self, _root: PlatformNode, _container_id: &str) -> PlatformResult<()> {
        // TODO: get Window by container_id, set root as Content
        Ok(())
    }

    fn patch(&self, _old: &PlatformNode, _new: &PlatformNode) -> PlatformResult<()> {
        // TODO: diff and apply WinUI mutations
        Ok(())
    }
}
