use crate::ast::*;

/// Generates C# / WinUI 3 (XAML + Code-Behind) code for the Windows Desktop target.
/// 
/// # Arguments
/// * `ast` - Processed LiquidAST tree.
pub fn generate_winui(ast: &LiquidAST) -> String {
    let mut output = String::new();
    
    output.push_str("/* === C# Common Helpers === */\n");
    output.push_str("using Microsoft.UI.Xaml;\n");
    output.push_str("using Microsoft.UI.Xaml.Controls;\n");
    output.push_str("using System.ComponentModel;\n");
    output.push_str("using System.Runtime.CompilerServices;\n\n");
    output.push_str("namespace LiquidApp\n{\n");
    output.push_str("    public static class WinUIExtensions\n    {\n");
    output.push_str("        public static T With<T>(this T item, System.Action<T> action)\n");
    output.push_str("        {\n");
    output.push_str("            action(item);\n");
    output.push_str("            return item;\n");
    output.push_str("        }\n");
    output.push_str("    }\n\n");
    output.push_str("    public static class Storage\n    {\n");
    output.push_str("        private static readonly System.Collections.Generic.Dictionary<string, string> _store = new System.Collections.Generic.Dictionary<string, string>();\n");
    output.push_str("        public static void Set(string key, string value)\n");
    output.push_str("        {\n");
    output.push_str("            _store[key] = value;\n");
    output.push_str("        }\n");
    output.push_str("        public static string Get(string key)\n");
    output.push_str("        {\n");
    output.push_str("            return _store.TryGetValue(key, out var val) ? val : \"\";\n");
    output.push_str("        }\n");
    output.push_str("    }\n");
    output.push_str("}\n\n");
    
    let store_names: Vec<String> = ast.classes.iter()
        .filter(|c| c.extends_class == "Store")
        .map(|c| c.name.clone())
        .collect();
    
    let custom_components: Vec<String> = ast.classes.iter()
        .filter(|c| c.extends_class == "Component")
        .map(|c| c.name.clone())
        .collect();
    
    for comp in &ast.classes {
        if comp.extends_class == "Store" {
            output.push_str(&generate_store(comp));
        } else {
            output.push_str(&generate_component(comp, &store_names, &custom_components));
        }
    }
    
    output
}

/// Generates XAML and C# Code-Behind partial class representation for a component class.
fn generate_component(comp: &ClassDecl, store_names: &[String], custom_components: &[String]) -> String {
    let mut code = String::new();
    
    // Check if the component rendering contains a Navigator element
    let nav_el = find_navigator(&comp.render.element);
    let has_nav = nav_el.is_some();
    let mut nav_route_var = String::new();
    let mut nav_routes = Vec::new();
    
    if let Some(nav) = nav_el {
        for prop in &nav.props {
            if prop.name == "initialRoute" {
                if let Value::Identifier(id) = &prop.value {
                    nav_route_var = id.clone();
                }
            }
            if prop.name == "children" {
                if let Value::Array(arr) = &prop.value {
                    for val in arr {
                        if let Value::Element(route_el) = val {
                            if route_el.name == "Route" {
                                let mut path = String::new();
                                let mut page = String::new();
                                for rp in &route_el.props {
                                    if rp.name == "path" {
                                        if let Value::StringLit(p) = &rp.value {
                                            path = p.clone();
                                        }
                                    }
                                    if rp.name == "page" {
                                        if let Value::Identifier(pg) = &rp.value {
                                            page = pg.clone();
                                        }
                                    }
                                }
                                if !path.is_empty() && !page.is_empty() {
                                    nav_routes.push((path, page));
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    // --- 1. XAML GENERATION ---
    code.push_str("<!-- === XAML (Counter.xaml) === -->\n");
    code.push_str(&format!("<UserControl\n    x:Class=\"LiquidApp.{}\"\n    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:local=\"using:LiquidApp\">\n", comp.name));
    let mut if_counter = 1;
    code.push_str(&generate_xaml_element(&comp.render.element, 4, &mut if_counter, custom_components));
    code.push_str("\n</UserControl>\n");
    
    // --- 2. C# CODE-BEHIND GENERATION ---
    code.push_str("/* === C# Code-Behind (Counter.xaml.cs) === */\n");
    
    code.push_str("namespace LiquidApp\n{\n");
    code.push_str(&format!("    public sealed partial class {} : UserControl, INotifyPropertyChanged\n    {{\n", comp.name));
    
    // Private fields for backing states
    for prop in &comp.properties {
        let cs_type = match prop.type_name.as_str() {
            "int" | "Int" => "int",
            "double" | "Double" => "double",
            "bool" | "Bool" => "bool",
            "String" => "string",
            _ => &prop.type_name,
        };
        let val_str = match &prop.value {
            Value::NumberLit(n) => n.clone(),
            Value::StringLit(s) => format!("\"{}\"", s),
            Value::Identifier(id) => id.clone(),
            _ => "default".to_string(),
        };
        code.push_str(&format!("        private {} _{} = {};\n", cs_type, prop.name, val_str));
    }
    code.push_str("\n");
    
    // Public properties with OnPropertyChanged notifications
    for prop in &comp.properties {
        let cs_type = match prop.type_name.as_str() {
            "int" | "Int" => "int",
            "double" | "Double" => "double",
            "bool" | "Bool" => "bool",
            "String" => "string",
            _ => &prop.type_name,
        };
        let cap_name = format!("{}{}", &prop.name[0..1].to_uppercase(), &prop.name[1..]);
        code.push_str(&format!("        public {} {}\n        {{\n", cs_type, cap_name));
        code.push_str(&format!("            get => _{};\n", prop.name));
        code.push_str("            set\n            {\n");
        code.push_str(&format!("                if (_{} != value)\n", prop.name));
        code.push_str("                {\n");
        code.push_str(&format!("                    _{} = value;\n", prop.name));
        code.push_str("                    OnPropertyChanged();\n");
        
        if has_nav && prop.name == nav_route_var {
            code.push_str("                    this.UpdateNavigation();\n");
        }
        
        // Trigger computed/interpolated properties dependent on this property
        let mut computed_triggers = Vec::new();
        find_computed_properties(&comp.render.element, &prop.name, &mut computed_triggers);
        for trigger in computed_triggers {
            code.push_str(&format!("                    OnPropertyChanged(nameof({}));\n", trigger));
        }
        
        code.push_str("                }\n");
        code.push_str("            }\n        }\n\n");
    }
    
    // Declarations of computed properties for string interpolation
    let mut computed_decls = Vec::new();
    collect_computed_properties(&comp.render.element, &mut computed_decls);
    for (comp_prop_name, fmt_str) in computed_decls {
        code.push_str(&format!("        public string {} => $\"{}\";\n\n", comp_prop_name, fmt_str));
    }
    
    // Collect For, TextField and If elements
    let mut for_elements = Vec::new();
    collect_for_elements(&comp.render.element, &mut for_elements);
    
    let mut textfield_elements = Vec::new();
    collect_textfield_elements(&comp.render.element, &mut textfield_elements);

    let mut if_elements = Vec::new();
    collect_if_elements(&comp.render.element, &mut if_elements);

    // Component constructor
    code.push_str(&format!("        public {}()\n        {{\n", comp.name));
    code.push_str("            this.InitializeComponent();\n");
    for i in 1..=if_elements.len() {
        code.push_str(&format!("            this.PropertyChanged += (s, e) => this.UpdateIfContainer_{}();\n", i));
        for store in store_names {
            code.push_str(&format!("            {}.Instance.PropertyChanged += (s, e) => this.UpdateIfContainer_{}();\n", store, i));
        }
    }
    for store in store_names {
        code.push_str(&format!("            {}.Instance.PropertyChanged += (s, e) => OnPropertyChanged(\"\");\n", store));
        for for_el in &for_elements {
            let mut items_val = String::new();
            for prop in &for_el.props {
                if prop.name == "items" {
                    items_val = translate_winui_value(&prop.value);
                }
            }
            if items_val.contains(&format!("{}.", store)) || items_val.contains(&format!("{}.", store.to_lowercase())) {
                let mut items_name = "Items".to_string();
                for prop in &for_el.props {
                    if prop.name == "items" {
                        if let Value::Identifier(id) = &prop.value {
                            items_name = clean_identifier_for_binding_name(id);
                        }
                    }
                }
                code.push_str(&format!("            {}.Instance.PropertyChanged += (s, e) => this.Update{}Container();\n", store, items_name));
            }
        }
    }
    
    for for_el in &for_elements {
        let mut items_name = "Items".to_string();
        let mut items_val = String::new();
        for prop in &for_el.props {
            if prop.name == "items" {
                items_val = translate_winui_value(&prop.value);
                if let Value::Identifier(id) = &prop.value {
                    items_name = clean_identifier_for_binding_name(id);
                }
            }
        }
        if !items_val.contains('.') {
            code.push_str(&format!("            this.PropertyChanged += (s, e) => {{ if (e.PropertyName == \"{}\") this.Update{}Container(); }};\n", items_name, items_name));
        }
    }
    
    if has_nav {
        code.push_str("            this.UpdateNavigation();\n");
    }
    
    for for_el in &for_elements {
        let mut items_name = "Items".to_string();
        for prop in &for_el.props {
            if prop.name == "items" {
                if let Value::Identifier(id) = &prop.value {
                    items_name = clean_identifier_for_binding_name(id);
                }
            }
        }
        code.push_str(&format!("            this.Update{}Container();\n", items_name));
    }
    
    for i in 1..=if_elements.len() {
        code.push_str(&format!("            this.UpdateIfContainer_{}();\n", i));
    }
    
    let has_on_init = comp.methods.iter().any(|m| m.name == "onInit");
    let has_on_dispose = comp.methods.iter().any(|m| m.name == "onDispose");
    if has_on_init {
        code.push_str("            this.Loaded += (s, e) => { this.OnInit(); };\n");
    }
    if has_on_dispose {
        code.push_str("            this.Unloaded += (s, e) => { this.OnDispose(); };\n");
    }
    code.push_str("        }\n\n");
    
    // Switch-based Navigation rendering generator helper
    if has_nav {
        code.push_str("        private void UpdateNavigation()\n        {\n");
        code.push_str("            if (this.NavigatorContainer == null) return;\n");
        code.push_str(&format!("            switch (this._{})\n            {{\n", nav_route_var));
        for (path, page) in &nav_routes {
            code.push_str(&format!("                case \"{}\":\n", path));
            code.push_str(&format!("                    this.NavigatorContainer.Content = new {}();\n", page));
            code.push_str("                    break;\n");
        }
        code.push_str("            }\n        }\n\n");
    }

    // Dynamic lists update methods for For loops
    for for_el in &for_elements {
        let mut items_val = String::from("new string[0]");
        let mut item_var = "item".to_string();
        let mut items_name = "Items".to_string();
        let mut child_el = None;
        for prop in &for_el.props {
            match prop.name.as_str() {
                "items" => {
                    items_val = translate_winui_store_expr(&translate_winui_value(&prop.value));
                    if let Value::Identifier(id) = &prop.value {
                        items_name = clean_identifier_for_binding_name(id);
                    }
                }
                "item" => {
                    if let Value::StringLit(s) = &prop.value {
                        item_var = s.clone();
                    }
                }
                "child" => {
                    if let Value::Element(c_el) = &prop.value {
                        child_el = Some(c_el);
                    }
                }
                _ => {}
            }
        }
        
        let creation_stmt = if let Some(child) = child_el {
            generate_csharp_element_creation(child, &item_var, custom_components)
        } else {
            "new Border()".to_string()
        };
        
        code.push_str(&format!("        private void Update{}Container()\n        {{\n", items_name));
        code.push_str(&format!("            if (this.{}Container == null) return;\n", items_name));
        code.push_str(&format!("            this.{}Container.Children.Clear();\n", items_name));
        code.push_str(&format!("            foreach (var {} in {})\n            {{\n", item_var, items_val));
        code.push_str(&format!("                var uiEl = {};\n", creation_stmt));
        code.push_str(&format!("                this.{}Container.Children.Add(uiEl);\n", items_name));
        code.push_str("            }\n");
        code.push_str("        }\n\n");
    }

    // Dynamic If elements update helper methods
    for (idx, if_el) in if_elements.iter().enumerate() {
        let i = idx + 1;
        let mut condition = String::from("true");
        let mut child_str = String::from("null");
        let mut fallback_str = String::from("null");
        for prop in &if_el.props {
            if prop.name == "condition" {
                condition = translate_csharp_value_with_item(&prop.value, "");
            } else if prop.name == "child" {
                if let Value::Element(child_el) = &prop.value {
                    child_str = generate_csharp_element_creation(child_el, "", custom_components);
                }
            } else if prop.name == "fallback" {
                if let Value::Element(fallback_el) = &prop.value {
                    fallback_str = generate_csharp_element_creation(fallback_el, "", custom_components);
                }
            }
        }
        code.push_str(&format!("        private void UpdateIfContainer_{}()\n        {{\n", i));
        code.push_str(&format!("            if (this.IfContainer_{} == null) return;\n", i));
        code.push_str(&format!("            this.IfContainer_{}.Content = ({}) ? (Microsoft.UI.Xaml.UIElement)({}) : (Microsoft.UI.Xaml.UIElement)({});\n", i, condition, child_str, fallback_str));
        code.push_str("        }\n\n");
    }

    // TextField changed handlers
    for tf_el in &textfield_elements {
        let mut value_var = String::new();
        let mut on_changed_cb = String::new();
        for prop in &tf_el.props {
            if prop.name == "value" {
                value_var = match &prop.value {
                    Value::Identifier(id) => id.clone(),
                    _ => "".to_string(),
                };
            } else if prop.name == "onChanged" {
                if let Value::Identifier(id) = &prop.value {
                    on_changed_cb = id.clone();
                }
            }
        }
        if !on_changed_cb.is_empty() {
            let clean_binding_name = clean_identifier_for_binding_name(&value_var);
            let cap_cb = format!("{}{}", &on_changed_cb[0..1].to_uppercase(), &on_changed_cb[1..]);
            code.push_str(&format!("        private void {}_TextChanged(object sender, Microsoft.UI.Xaml.Controls.TextChangedEventArgs e)\n        {{\n", clean_binding_name));
            let cap_binding = if value_var.contains('.') {
                translate_winui_store_expr(&value_var)
            } else {
                format!("{}{}", &value_var[0..1].to_uppercase(), &value_var[1..])
            };
            code.push_str(&format!("            if (sender is TextBox tb) {{ {} = tb.Text; }}\n", cap_binding));
            code.push_str(&format!("            this.{}();\n", cap_cb));
            code.push_str("        }\n\n");
        }
    }
    
    // Click event handler methods and actual method bodies
    for method in &comp.methods {
        let cap_method = format!("{}{}", &method.name[0..1].to_uppercase(), &method.name[1..]);
        let cs_type = match method.type_name.as_str() {
            "void" | "" => "void".to_string(),
            "int" | "Int" => "int".to_string(),
            "double" | "Double" => "double".to_string(),
            "bool" | "Bool" => "bool".to_string(),
            "String" => "string".to_string(),
            other => other.to_string(),
        };
        code.push_str(&format!("        public {} {}()\n        {{\n", cs_type, cap_method));
        for stmt in &method.statements {
            let translated = translate_winui_statement(stmt);
            code.push_str(&format!("            {}", translated.trim_start()));
        }
        code.push_str("        }\n\n");

        code.push_str(&format!("        private void {}_Click(object sender, RoutedEventArgs e)\n        {{\n", cap_method));
        code.push_str(&format!("            this.{}();\n", cap_method));
        code.push_str("        }\n\n");
    }
    
    // INotifyPropertyChanged interface implementation
    code.push_str("        public event PropertyChangedEventHandler PropertyChanged;\n");
    code.push_str("        private void OnPropertyChanged([CallerMemberName] string name = null)\n");
    code.push_str("        {\n");
    code.push_str("            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));\n");
    code.push_str("        }\n");
    code.push_str("    }\n}\n");
    
    code
}

/// Recursively generates XAML markup from Liquid elements.
fn generate_xaml_element(el: &Element, indent_level: usize, if_counter: &mut usize, custom_components: &[String]) -> String {
    let indent = "    ".repeat(indent_level);
    let mut code = String::new();
    
    if custom_components.contains(&el.name) {
        let mut props_str = String::new();
        for prop in &el.props {
            let cap_prop = format!("{}{}", &prop.name[0..1].to_uppercase(), &prop.name[1..]);
            let bind_val = translate_winui_binding(&prop.value);
            props_str.push_str(&format!(" {}=\"{}\"", cap_prop, bind_val));
        }
        if props_str.is_empty() {
            return format!("{}<local:{} />\n", indent, el.name);
        } else {
            return format!("{}<local:{}{} />\n", indent, el.name, props_str);
        }
    }
    
    match el.name.as_str() {
        "If" => {
            let current_if_index = *if_counter;
            *if_counter += 1;
            code.push_str(&format!("{}<ContentControl x:Name=\"IfContainer_{}\" />\n", indent, current_if_index));
        }
        "Column" | "Row" => {
            let mut orientation = "";
            if el.name == "Row" {
                orientation = " Orientation=\"Horizontal\"";
            }
            
            let mut spacing_val = String::from("16");
            let mut align_val = "Center";
            let mut children_val = None;
            
            for prop in &el.props {
                match prop.name.as_str() {
                    "alignment" => {
                        align_val = "Center";
                    }
                    "spacing" => {
                        spacing_val = translate_winui_value(&prop.value);
                    }
                    "children" => {
                        children_val = Some(&prop.value);
                    }
                    _ => {}
                }
            }
            
            let align_attr = if el.name == "Column" {
                format!(" HorizontalAlignment=\"{}\"", align_val)
            } else {
                format!(" VerticalAlignment=\"{}\"", align_val)
            };
            
            code.push_str(&format!("{}<StackPanel{}{} Spacing=\"{}\">\n", indent, orientation, align_attr, spacing_val));
            if let Some(Value::Array(arr)) = children_val {
                for v in arr {
                    if let Value::Element(child_el) = v {
                        code.push_str(&generate_xaml_element(child_el, indent_level + 1, if_counter, custom_components));
                    }
                }
            }
            code.push_str(&format!("{}</StackPanel>\n", indent));
        }
        "Text" => {
            let mut text_bind = String::from("\"\"");
            let mut font_size = String::new();
            let mut font_weight = String::new();
            let mut foreground = String::new();
            
            for prop in &el.props {
                match prop.name.as_str() {
                    "label" | "text" => {
                        text_bind = translate_winui_binding(&prop.value);
                    }
                    "style" => {
                        if let Value::Element(style_el) = &prop.value {
                            if style_el.name == "TextStyle" {
                                for style_prop in &style_el.props {
                                    match style_prop.name.as_str() {
                                        "fontSize" => {
                                            font_size = format!(" FontSize=\"{}\"", translate_winui_value(&style_prop.value));
                                        }
                                        "weight" => {
                                            let weight = translate_winui_value(&style_prop.value);
                                            let w_val = if weight.contains("bold") || weight.contains("Bold") {
                                                "Bold"
                                            } else {
                                                "Normal"
                                            };
                                            font_weight = format!(" FontWeight=\"{}\"", w_val);
                                        }
                                        "color" => {
                                            let color = translate_winui_value(&style_prop.value);
                                            let clean_color = color.replace("Colors.", "").replace("Color.", "").replace("\"", "");
                                            foreground = format!(" Foreground=\"{}\"", clean_color);
                                        }
                                        _ => {}
                                    }
                                }
                            }
                        }
                    }
                    _ => {}
                }
            }
            code.push_str(&format!("{}<TextBlock Text=\"{}\"{}{}{} />\n", indent, text_bind, font_size, font_weight, foreground));
        }
        "Button" => {
            let mut content_val = String::from("\"\"");
            let mut click_handler = String::from("");
            
            for prop in &el.props {
                match prop.name.as_str() {
                    "label" => {
                        content_val = translate_winui_value(&prop.value);
                    }
                    "onPressed" => {
                        if let Value::Identifier(id) = &prop.value {
                            let capitalized_id = format!("{}{}", &id[0..1].to_uppercase(), &id[1..]);
                            click_handler = format!(" Click=\"{}_Click\"", capitalized_id);
                        }
                    }
                    _ => {}
                }
            }
            
            code.push_str(&format!("{}<Button Content=\"{}\"{} />\n", indent, content_val.trim_matches('"'), click_handler));
        }
        "For" => {
            let mut items_name = "Items".to_string();
            for prop in &el.props {
                if prop.name == "items" {
                    if let Value::Identifier(id) = &prop.value {
                        items_name = clean_identifier_for_binding_name(id);
                    }
                }
            }
            code.push_str(&format!("{}<StackPanel x:Name=\"{}Container\" />\n", indent, items_name));
        }
        "TextField" => {
            let mut value_var = String::new();
            let mut on_changed_cb = String::new();
            for prop in &el.props {
                if prop.name == "value" {
                    value_var = match &prop.value {
                        Value::Identifier(id) => id.clone(),
                        _ => "".to_string(),
                    };
                } else if prop.name == "onChanged" {
                    if let Value::Identifier(id) = &prop.value {
                        on_changed_cb = id.clone();
                    }
                }
            }
            let cap_binding = if value_var.contains('.') {
                translate_winui_store_expr(&value_var)
            } else {
                format!("{}{}", &value_var[0..1].to_uppercase(), &value_var[1..])
            };
            
            let clean_binding_name = clean_identifier_for_binding_name(&value_var);
            let text_changed_attr = if on_changed_cb.is_empty() {
                "".to_string()
            } else {
                format!(" TextChanged=\"{}_TextChanged\"", clean_binding_name)
            };
            
            code.push_str(&format!("{}<TextBox Text=\"{{x:Bind {}, Mode=TwoWay}}\"{} />\n", indent, cap_binding, text_changed_attr));
        }
        "Container" => {
            let mut padding = String::new();
            let mut color = String::new();
            let mut radius = String::new();
            let mut child_val = None;
            
            for prop in &el.props {
                match prop.name.as_str() {
                    "padding" => {
                        padding = format!(" Padding=\"{}\"", translate_winui_value(&prop.value));
                    }
                    "color" => {
                        let val = translate_winui_value(&prop.value);
                        let clean_color = val.replace("Colors.", "").replace("Color.", "").replace("\"", "");
                        color = format!(" Background=\"{}\"", clean_color);
                    }
                    "borderRadius" => {
                        radius = format!(" CornerRadius=\"{}\"", translate_winui_value(&prop.value));
                    }
                    "child" => {
                        child_val = Some(&prop.value);
                    }
                    _ => {}
                }
            }
            
            code.push_str(&format!("{}<Border{}{}{}>\n", indent, padding, color, radius));
            if let Some(Value::Element(child_el)) = child_val {
                code.push_str(&generate_xaml_element(child_el, indent_level + 1, if_counter, custom_components));
            }
            code.push_str(&format!("{}</Border>\n", indent));
        }
        "Navigator" => {
            code.push_str(&format!("{}<ContentControl x:Name=\"NavigatorContainer\" HorizontalAlignment=\"Center\" VerticalAlignment=\"Center\" />\n", indent));
        }
        "Route" => {}
        _ => {
            code.push_str(&format!("{}<!-- Unknown Element {} -->\n", indent, el.name));
        }
    }
    
    code
}

/// Translates Value into a simple WinUI representation.
fn translate_winui_value(val: &Value) -> String {
    match val {
        Value::StringLit(s) => format!("\"{}\"", s),
        Value::NumberLit(n) => n.clone(),
        Value::Identifier(id) => id.clone(),
        _ => "\"\"".to_string(),
    }
}

/// Translates Value into WinUI 3 {x:Bind} data-binding markup.
fn translate_winui_binding(val: &Value) -> String {
    match val {
        Value::StringLit(s) => {
            if s.contains('$') {
                let chars: Vec<char> = s.chars().collect();
                let mut i = 0;
                let mut computed_prop_name = String::new();
                while i < chars.len() {
                    if chars[i] == '$' && i + 1 < chars.len() && chars[i+1].is_alphabetic() {
                        let mut var_name = String::new();
                        i += 1;
                        while i < chars.len() && (chars[i].is_alphanumeric() || chars[i] == '_' || chars[i] == '.') {
                            var_name.push(chars[i]);
                            i += 1;
                        }
                        let clean_var = clean_identifier_for_binding_name(&var_name);
                        computed_prop_name.push_str(&clean_var);
                    } else {
                        i += 1;
                    }
                }
                format!("{{x:Bind {}, Mode=OneWay}}", computed_prop_name)
            } else {
                s.clone()
            }
        }
        Value::Identifier(id) => {
            let cap_var = if id.contains('.') {
                translate_winui_store_expr(id)
            } else {
                format!("{}{}", &id[0..1].to_uppercase(), &id[1..])
            };
            format!("{{x:Bind {}, Mode=OneWay}}", cap_var)
        }
        Value::NumberLit(n) => n.clone(),
        _ => "\"\"".to_string(),
    }
}

/// Traverses render elements to identify properties linked to string interpolation.
fn find_computed_properties(el: &Element, target_prop_name: &str, list: &mut Vec<String>) {
    for prop in &el.props {
        if prop.name == "label" || prop.name == "text" {
            if let Value::StringLit(s) = &prop.value {
                if s.contains('$') {
                    let mut is_affected = false;
                    let mut comp_prop_name = String::new();
                    let chars: Vec<char> = s.chars().collect();
                    let mut i = 0;
                    
                    while i < chars.len() {
                        if chars[i] == '$' && i + 1 < chars.len() && chars[i+1].is_alphabetic() {
                            let mut var_name = String::new();
                            i += 1;
                            while i < chars.len() && (chars[i].is_alphanumeric() || chars[i] == '_') {
                                var_name.push(chars[i]);
                                i += 1;
                            }
                            if var_name == target_prop_name {
                                is_affected = true;
                            }
                            let cap_var = format!("{}{}", &var_name[0..1].to_uppercase(), &var_name[1..]);
                            comp_prop_name.push_str(&cap_var);
                        } else {
                            i += 1;
                        }
                    }
                    if is_affected {
                        list.push(comp_prop_name);
                    }
                }
            }
        } else if prop.name == "children" {
            if let Value::Array(arr) = &prop.value {
                for val in arr {
                    if let Value::Element(child_el) = val {
                        find_computed_properties(child_el, target_prop_name, list);
                    }
                }
            }
        }
    }
}

/// Traverses render elements to collect all computed properties.
fn collect_computed_properties(el: &Element, list: &mut Vec<(String, String)>) {
    for prop in &el.props {
        if prop.name == "label" || prop.name == "text" {
            if let Value::StringLit(s) = &prop.value {
                if s.contains('$') {
                    let mut comp_prop_name = String::new();
                    let mut fmt_str = String::new();
                    let chars: Vec<char> = s.chars().collect();
                    let mut i = 0;
                    
                    while i < chars.len() {
                        if chars[i] == '$' && i + 1 < chars.len() && chars[i+1].is_alphabetic() {
                            let mut var_name = String::new();
                            i += 1;
                            while i < chars.len() && (chars[i].is_alphanumeric() || chars[i] == '_' || chars[i] == '.') {
                                var_name.push(chars[i]);
                                i += 1;
                            }
                            let clean_var = clean_identifier_for_binding_name(&var_name);
                            let mapped_var = if var_name.contains('.') {
                                translate_winui_store_expr(&var_name)
                            } else {
                                format!("{}{}", &var_name[0..1].to_uppercase(), &var_name[1..])
                            };
                            comp_prop_name.push_str(&clean_var);
                            fmt_str.push_str(&format!("{{{}}}", mapped_var));
                        } else {
                            fmt_str.push(chars[i]);
                            i += 1;
                        }
                    }
                    list.push((comp_prop_name, fmt_str));
                }
            }
        } else if prop.name == "children" {
            if let Value::Array(arr) = &prop.value {
                for val in arr {
                    if let Value::Element(child_el) = val {
                        collect_computed_properties(child_el, list);
                    }
                }
            }
        }
    }
}

/// Recursive helper to traverse the tree and locate a Navigator element.
fn find_navigator(el: &Element) -> Option<&Element> {
    if el.name == "Navigator" {
        return Some(el);
    }
    for prop in &el.props {
        if prop.name == "children" {
            if let Value::Array(arr) = &prop.value {
                for val in arr {
                    if let Value::Element(child_el) = val {
                        if let Some(nav) = find_navigator(child_el) {
                            return Some(nav);
                        }
                    }
                }
            }
        }
    }
    None
}

fn clean_identifier_for_binding_name(id: &str) -> String {
    let parts: Vec<String> = id.split('.')
        .map(|p| format!("{}{}", &p[0..1].to_uppercase(), &p[1..]))
        .collect();
    parts.join("")
}

fn translate_winui_store_expr(id: &str) -> String {
    if id.contains('.') {
        let parts: Vec<&str> = id.split('.').collect();
        if parts.len() == 2 {
            let store_inst = parts[0];
            let member = parts[1];
            let class_name = format!("{}{}", &store_inst[0..1].to_uppercase(), &store_inst[1..]);
            let cap_member = format!("{}{}", &member[0..1].to_uppercase(), &member[1..]);
            return format!("{}.Instance.{}", class_name, cap_member);
        }
    }
    id.to_string()
}

/// Generates a C# class for a reactive store.
fn generate_store(comp: &ClassDecl) -> String {
    let mut code = String::new();
    
    code.push_str("/* === C# Store === */\n");
    code.push_str("using System.ComponentModel;\n");
    code.push_str("using System.Runtime.CompilerServices;\n\n");
    code.push_str("namespace LiquidApp\n{\n");
    code.push_str(&format!("    public class {} : INotifyPropertyChanged\n    {{\n", comp.name));
    code.push_str(&format!("        public static readonly {} Instance = new {}();\n\n", comp.name, comp.name));
    
    // Private backing fields and public properties
    for prop in &comp.properties {
        let cs_type = match prop.type_name.as_str() {
            "int" | "Int" => "int",
            "double" | "Double" => "double",
            "bool" | "Bool" => "bool",
            "String" => "string",
            _ => &prop.type_name,
        };
        let cap_name = format!("{}{}", &prop.name[0..1].to_uppercase(), &prop.name[1..]);
        let val_str = match &prop.value {
            Value::NumberLit(n) => n.clone(),
            Value::StringLit(s) => format!("\"{}\"", s),
            Value::Identifier(id) => id.clone(),
            _ => "default".to_string(),
        };
        
        code.push_str(&format!("        private {} _{} = {};\n", cs_type, prop.name, val_str));
        code.push_str(&format!("        public {} {}\n        {{\n", cs_type, cap_name));
        code.push_str(&format!("            get => _{};\n", prop.name));
        code.push_str("            set\n            {\n");
        code.push_str(&format!("                if (_{} != value)\n", prop.name));
        code.push_str("                {\n");
        code.push_str(&format!("                    _{} = value;\n", prop.name));
        code.push_str(&format!("                    OnPropertyChanged(nameof({}));\n", cap_name));
        code.push_str("                }\n            }\n        }\n\n");
    }
    
    // Methods
    for method in &comp.methods {
        let cap_method = format!("{}{}", &method.name[0..1].to_uppercase(), &method.name[1..]);
        let cs_type = match method.type_name.as_str() {
            "void" | "" => "void".to_string(),
            "int" | "Int" => "int".to_string(),
            "double" | "Double" => "double".to_string(),
            "bool" | "Bool" => "bool".to_string(),
            "String" => "string".to_string(),
            other => other.to_string(),
        };
        code.push_str(&format!("        public {} {}()\n        {{\n", cs_type, cap_method));
        for stmt in &method.statements {
            let translated = translate_winui_statement(stmt);
            code.push_str(&format!("            {}", translated.trim_start()));
        }
        code.push_str("        }\n\n");
    }
    
    // INotifyPropertyChanged interface
    code.push_str("        public event PropertyChangedEventHandler PropertyChanged;\n");
    code.push_str("        private void OnPropertyChanged([CallerMemberName] string name = null)\n");
    code.push_str("        {\n");
    code.push_str("            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));\n");
    code.push_str("        }\n");
    code.push_str("    }\n}\n\n");
    
    code
}

fn translate_winui_statement(stmt: &Statement) -> String {
    match stmt {
        Statement::Return(val) => {
            let val_str = translate_winui_value(val);
            let final_val_cap = if let Value::Identifier(id) = val {
                if id.contains('.') {
                    translate_winui_store_expr(id)
                } else {
                    format!("this.{}{}", &id[0..1].to_uppercase(), &id[1..])
                }
            } else {
                val_str
            };
            format!("return {};\n", final_val_cap)
        }
        Statement::Expr(expr) => {
            if expr.name == "Http.get" {
                if let Some(ref args) = expr.args {
                    if args.len() >= 2 {
                        let url = translate_winui_value(&args[0]);
                        if let Value::Identifier(ref cb) = args[1] {
                            let cap_cb = format!("{}{}", &cb[0..1].to_uppercase(), &cb[1..]);
                            return format!("// Http.get mock\n            var _url = {};\n            this.{}(\"Mock HTTP GET Response data\");\n", url, cap_cb);
                        }
                    }
                }
            } else if expr.name == "Http.post" {
                if let Some(ref args) = expr.args {
                    if args.len() >= 3 {
                        let url = translate_winui_value(&args[0]);
                        let body = translate_winui_value(&args[1]);
                        if let Value::Identifier(ref cb) = args[2] {
                            let cap_cb = format!("{}{}", &cb[0..1].to_uppercase(), &cb[1..]);
                            return format!("// Http.post mock\n            var _url = {};\n            var _body = {};\n            this.{}(\"Mock HTTP POST Response data\");\n", url, body, cap_cb);
                        }
                    }
                }
            } else if expr.name == "Location.current" {
                if let Some(ref args) = expr.args {
                    if args.len() >= 1 {
                        if let Value::Identifier(ref cb) = args[0] {
                            let cap_cb = format!("{}{}", &cb[0..1].to_uppercase(), &cb[1..]);
                            return format!("// Location.current mock\n            this.{}(\"-6.2088,106.8456\");\n", cap_cb);
                        }
                    }
                }
            } else if expr.name == "Notification.show" {
                if let Some(ref args) = expr.args {
                    if args.len() >= 2 {
                        let title = translate_winui_value(&args[0]);
                        let body = translate_winui_value(&args[1]);
                        return format!("// Notification.show mock\n            var _title = {};\n            var _body = {};\n", title, body);
                    }
                }
            } else if expr.name == "Storage.set" {
                if let Some(ref args) = expr.args {
                    if args.len() >= 2 {
                        let key = translate_winui_value(&args[0]);
                        let val = translate_winui_value(&args[1]);
                        return format!("Storage.Set({}, {});\n", key, val);
                    }
                }
            } else if expr.name == "Storage.get" {
                if let Some(ref args) = expr.args {
                    if args.len() >= 1 {
                        let key = translate_winui_value(&args[0]);
                        return format!("Storage.Get({});\n", key);
                    }
                }
            }

            let prefix = if expr.name.contains('.') { "" } else { "this." };
            let mapped_expr = if expr.name.contains('.') {
                translate_winui_store_expr(&expr.name)
            } else {
                let parts: Vec<String> = expr.name.split('.')
                    .map(|p| format!("{}{}", &p[0..1].to_uppercase(), &p[1..]))
                    .collect();
                parts.join(".")
            };

            if let Some(op) = &expr.op {
                if op == "++" {
                    format!("{}{}++;\n", prefix, mapped_expr)
                } else if op == "--" {
                    format!("{}{}--;\n", prefix, mapped_expr)
                } else {
                    format!("{}{};\n", prefix, mapped_expr)
                }
            } else if let Some(ref args) = expr.args {
                let args_strs: Vec<String> = args.iter().map(|v| translate_winui_value(v)).collect();
                format!("{}{}({});\n", prefix, mapped_expr, args_strs.join(", "))
            } else {
                format!("{}{}();\n", prefix, mapped_expr)
            }
        }
    }
}

fn collect_for_elements<'a>(el: &'a Element, list: &mut Vec<&'a Element>) {
    if el.name == "For" {
        list.push(el);
    }
    for prop in &el.props {
        if prop.name == "children" || prop.name == "child" {
            match &prop.value {
                Value::Array(arr) => {
                    for val in arr {
                        if let Value::Element(child_el) = val {
                            collect_for_elements(child_el, list);
                        }
                    }
                }
                Value::Element(child_el) => {
                    collect_for_elements(child_el, list);
                }
                _ => {}
            }
        }
    }
}

fn collect_textfield_elements<'a>(el: &'a Element, list: &mut Vec<&'a Element>) {
    if el.name == "TextField" {
        list.push(el);
    }
    for prop in &el.props {
        if prop.name == "children" || prop.name == "child" {
            match &prop.value {
                Value::Array(arr) => {
                    for val in arr {
                        if let Value::Element(child_el) = val {
                            collect_textfield_elements(child_el, list);
                        }
                    }
                }
                Value::Element(child_el) => {
                    collect_textfield_elements(child_el, list);
                }
                _ => {}
            }
        }
    }
}

fn generate_csharp_element_creation(el: &Element, item_var: &str, custom_components: &[String]) -> String {
    if custom_components.contains(&el.name) {
        let mut prop_assignments = Vec::new();
        for prop in &el.props {
            let cs_val = translate_csharp_value_with_item(&prop.value, item_var);
            let cap_prop = format!("{}{}", &prop.name[0..1].to_uppercase(), &prop.name[1..]);
            prop_assignments.push(format!("{} = {}", cap_prop, cs_val));
        }
        return format!("new {} {{ {} }}", el.name, prop_assignments.join(", "));
    }

    match el.name.as_str() {
        "If" => {
            let mut condition = String::from("true");
            let mut child_str = String::from("null");
            let mut fallback_str = String::from("null");
            for prop in &el.props {
                if prop.name == "condition" {
                    condition = translate_csharp_value_with_item(&prop.value, item_var);
                } else if prop.name == "child" {
                    if let Value::Element(child_el) = &prop.value {
                        child_str = generate_csharp_element_creation(child_el, item_var, custom_components);
                    }
                } else if prop.name == "fallback" {
                    if let Value::Element(fallback_el) = &prop.value {
                        fallback_str = generate_csharp_element_creation(fallback_el, item_var, custom_components);
                    }
                }
            }
            format!("(({}) ? (Microsoft.UI.Xaml.UIElement)({}) : (Microsoft.UI.Xaml.UIElement)({}))", condition, child_str, fallback_str)
        }
        "Text" => {
            let mut text_val = String::from("\"\"");
            let mut font_size = String::new();
            let mut font_weight = String::new();
            let mut foreground = String::new();
            
            for prop in &el.props {
                if prop.name == "text" || prop.name == "label" {
                    text_val = translate_csharp_value_with_item(&prop.value, item_var);
                } else if prop.name == "style" {
                    if let Value::Element(style_el) = &prop.value {
                        if style_el.name == "TextStyle" {
                            for sp in &style_el.props {
                                if sp.name == "fontSize" {
                                    font_size = format!("FontSize = {}, ", translate_csharp_value_with_item(&sp.value, item_var));
                                } else if sp.name == "weight" {
                                    let w = translate_csharp_value_with_item(&sp.value, item_var);
                                    let weight_val = if w.contains("bold") || w.contains("Bold") {
                                        "Microsoft.UI.Text.FontWeights.Bold"
                                    } else {
                                        "Microsoft.UI.Text.FontWeights.Normal"
                                    };
                                    font_weight = format!("FontWeight = {}, ", weight_val);
                                } else if sp.name == "color" {
                                    let c = translate_csharp_value_with_item(&sp.value, item_var);
                                    let clean_color = c.replace("Colors.", "").replace("Color.", "").replace("\"", "");
                                    foreground = format!("Foreground = new Microsoft.UI.Xaml.Media.SolidColorBrush(Windows.UI.ColorHelper.ToColor(\"{}\")), ", clean_color);
                                }
                            }
                        }
                    }
                }
            }
            format!("new TextBlock {{ Text = {}, {}{}{} }}", text_val, font_size, font_weight, foreground)
        }
        "Button" => {
            let mut label = String::from("\"\"");
            let mut action = String::new();
            for prop in &el.props {
                if prop.name == "label" {
                    label = translate_csharp_value_with_item(&prop.value, item_var);
                } else if prop.name == "onPressed" {
                    if let Value::Identifier(id) = &prop.value {
                        let capitalized_id = format!("{}{}", &id[0..1].to_uppercase(), &id[1..]);
                        action = format!("Click += (s, e) => this.{}()", capitalized_id);
                    }
                }
            }
            if action.is_empty() {
                format!("new Button {{ Content = {} }}", label)
            } else {
                format!("(new Button {{ Content = {} }}).With(b => b.{})", label, action)
            }
        }
        "Container" => {
            let mut padding = String::from("new Thickness(0)");
            let mut color = String::from("null");
            let mut radius = String::from("new CornerRadius(0)");
            let mut child_str = String::from("null");
            
            for prop in &el.props {
                if prop.name == "padding" {
                    let p = translate_csharp_value_with_item(&prop.value, item_var);
                    padding = format!("new Thickness({})", p);
                } else if prop.name == "color" {
                    let c = translate_csharp_value_with_item(&prop.value, item_var);
                    let clean_color = c.replace("Colors.", "").replace("Color.", "").replace("\"", "");
                    color = format!("new SolidColorBrush(Windows.UI.ColorHelper.ToColor(\"{}\"))", clean_color);
                } else if prop.name == "borderRadius" {
                    let r = translate_csharp_value_with_item(&prop.value, item_var);
                    radius = format!("new CornerRadius({})", r);
                } else if prop.name == "child" {
                    if let Value::Element(child_el) = &prop.value {
                        child_str = generate_csharp_element_creation(child_el, item_var, custom_components);
                    }
                }
            }
            format!("new Border {{ Padding = {}, Background = {}, CornerRadius = {}, Child = {} }}", padding, color, radius, child_str)
        }
        "Column" | "Row" => {
            let mut orientation = "Orientation.Vertical";
            if el.name == "Row" {
                orientation = "Orientation.Horizontal";
            }
            let mut spacing = String::from("16");
            let mut children_str = Vec::new();
            
            for prop in &el.props {
                if prop.name == "spacing" {
                    spacing = translate_csharp_value_with_item(&prop.value, item_var);
                } else if prop.name == "children" {
                    if let Value::Array(arr) = &prop.value {
                        for val in arr {
                            if let Value::Element(child_el) = val {
                                children_str.push(generate_csharp_element_creation(child_el, item_var, custom_components));
                            }
                        }
                    }
                }
            }
            
            let mut build = format!("new StackPanel {{ Orientation = Orientation.{}, Spacing = {} }}", orientation.replace("Orientation.", ""), spacing);
            if !children_str.is_empty() {
                let add_statements: Vec<String> = children_str.iter().map(|c| format!("panel.Children.Add({});", c)).collect();
                build = format!("((System.Func<StackPanel>)(() => {{ var panel = {}; {}; return panel; }}))()", build, add_statements.join(" "));
            }
            build
        }
        _ => "new Border()".to_string()
    }
}

fn translate_csharp_value_with_item(val: &Value, item_var: &str) -> String {
    match val {
        Value::StringLit(s) => {
            if s.contains('$') {
                let mut clean = s.clone();
                let target = format!("${}", item_var);
                clean = clean.replace(&target, &format!("{{{}}}", item_var));
                if clean.contains('$') {
                    let chars: Vec<char> = clean.chars().collect();
                    let mut i = 0;
                    let mut res = String::new();
                    while i < chars.len() {
                        if chars[i] == '$' && i + 1 < chars.len() && chars[i+1].is_alphabetic() {
                            let mut var_name = String::new();
                            i += 1;
                            while i < chars.len() && (chars[i].is_alphanumeric() || chars[i] == '_' || chars[i] == '.') {
                                var_name.push(chars[i]);
                                i += 1;
                            }
                            if var_name == item_var {
                                res.push_str(&format!("{{{}}}", var_name));
                            } else if var_name.contains('.') {
                                let mapped = translate_winui_store_expr(&var_name);
                                res.push_str(&format!("{{{}}}", mapped));
                            } else {
                                let cap = format!("{}{}", &var_name[0..1].to_uppercase(), &var_name[1..]);
                                res.push_str(&format!("{{this.{}}}", cap));
                            }
                        } else {
                            res.push(chars[i]);
                            i += 1;
                        }
                    }
                    clean = res;
                }
                format!("$\"{}\"", clean)
            } else {
                format!("\"{}\"", s)
            }
        }
        Value::NumberLit(n) => n.clone(),
        Value::Identifier(id) => {
            if id == item_var {
                id.clone()
            } else if id.contains('.') {
                translate_winui_store_expr(id)
            } else {
                format!("this.{}{}", &id[0..1].to_uppercase(), &id[1..])
            }
        }
        _ => "\"\"".to_string()
    }
}

fn collect_if_elements<'a>(el: &'a Element, list: &mut Vec<&'a Element>) {
    if el.name == "If" {
        list.push(el);
    }
    for prop in &el.props {
        if prop.name == "children" || prop.name == "child" || prop.name == "fallback" {
            match &prop.value {
                Value::Array(arr) => {
                    for val in arr {
                        if let Value::Element(child_el) = val {
                            collect_if_elements(child_el, list);
                        }
                    }
                }
                Value::Element(child_el) => {
                    collect_if_elements(child_el, list);
                }
                _ => {}
            }
        }
    }
}

