//! VNode 到 GPU 渲染适配器
//!
//! 将虚拟 DOM 树转换为 GPU 绘制命令，实现高效的渲染管线。
//! 支持纯色背景、渐变背景、边框等 CSS 特性。

#[cfg(feature = "vue-sfc")]
use iris_dom::vnode::VNode;
#[cfg(feature = "webgpu-render")]
use iris_gpu::BatchRenderer;
use iris_gpu::DrawCommand;
use tracing::debug;

// ============================================
// 重新导出共享的 CSS 解析工具
// ============================================
pub use crate::css_utils::{
    parse_css_color, parse_css_unit, parse_border_width,
    parse_linear_gradient, parse_css_color_name, GradientStop, Background, GradientType,
    BorderInfo, TextInfo,
};
pub use crate::animation_engine::EasingFunction;

/// 动画类型
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub(crate) enum AnimationType {
    /// CSS Transition: 属性过渡动画
    Transition {
        property: String,
        duration: f32,  // 秒
        easing: EasingFunction,
    },
    /// CSS Animation: 关键帧动画 (预留)
    Keyframes {
        name: String,
        duration: f32,
        iteration_count: f32, // -1 表示无限
    },
}

/// 动画状态
#[allow(dead_code)]
#[derive(Debug, Clone)]
struct AnimationState {
    animation: AnimationType,
    start_value: f32,
    end_value: f32,
    current_value: f32,
    progress: f32, // 0.0 - 1.0
    is_running: bool,
}
/// VNode 渲染器
///
/// 负责将虚拟 DOM 树转换为 GPU 绘制命令。
pub struct VNodeRenderer;

#[allow(dead_code)]
impl VNodeRenderer {
    /// 渲染虚拟 DOM 树到 GPU
    ///
    /// 遍历 VNode 树，为每个可见元素生成绘制命令。
    ///
    /// # 参数
    ///
    /// * `vnode` - 虚拟 DOM 根节点
    /// * `renderer` - GPU 批渲染器
    /// * `parent_x` - 父元素 X 偏移
    /// * `parent_y` - 父元素 Y 偏移
    ///
    /// # 示例
    ///
    /// ```rust,ignore
    /// let vnode = VNode::element("div");
    /// let mut batch_renderer = // ... 创建渲染器
    /// VNodeRenderer::render(&vnode, &mut batch_renderer, 0.0, 0.0)?;
    /// batch_renderer.flush()?;
    /// ```
    pub fn render(
        vnode: &VNode,
        renderer: &mut BatchRenderer,
        parent_x: f32,
        parent_y: f32,
    ) -> Result<(), String> {
        // 默认文字颜色为黑色，字号 16px
        Self::render_recursive(vnode, renderer, parent_x, parent_y, [0.0, 0.0, 0.0, 1.0], 16.0)
    }

    /// 递归渲染 VNode
    fn render_recursive(
        vnode: &VNode,
        renderer: &mut BatchRenderer,
        parent_x: f32,
        parent_y: f32,
        inherited_color: [f32; 4],
        inherited_font_size: f32,
    ) -> Result<(), String> {
        match vnode {
            VNode::Element {
                tag,
                layout,
                styles,
                children,
                ..
            } => {
                // 从元素样式中提取 color 和 font-size（继承属性，覆盖父级值）
                let text_color = styles.get("color")
                    .and_then(|c| crate::css_utils::parse_css_color(c))
                    .unwrap_or(inherited_color);
                
                let font_size = styles.get("font-size")
                    .and_then(|s| {
                        let val = crate::css_utils::parse_css_unit(s);
                        if val > 0.0 { Some(val) } else { None }
                    })
                    .unwrap_or(inherited_font_size);

                // 如果有布局信息，渲染元素
                if let Some(layout_box) = layout {
                    let _box_model = &layout_box.box_model;
                    
                    // 计算绝对位置
                    let x = parent_x + layout_box.x;
                    let y = parent_y + layout_box.y;
                    let width = layout_box.width;
                    let height = layout_box.height;

                    // 跳过不可见元素
                    if width <= 0.0 || height <= 0.0 {
                        debug!(tag = tag, "Skipping zero-size element");
                    } else {
                        // 渲染背景（支持纯色和渐变）
                        Self::render_background(styles, x, y, width, height, renderer)?;
                        
                        // 渲染边框
                        Self::render_border(styles, x, y, width, height, renderer)?;
                        
                        // 递归渲染子节点（传递继承的文字样式）
                        for child in children {
                            Self::render_recursive(child, renderer, x, y, text_color, font_size)?;
                        }
                    }
                } else {
                    // 没有布局信息，仍然渲染子节点
                    for child in children {
                        Self::render_recursive(child, renderer, parent_x, parent_y, text_color, font_size)?;
                    }
                }
            }
            VNode::Text { content } => {
                // 使用父元素继承的文字颜色和字号渲染文本
                Self::render_text(content, parent_x, parent_y, renderer, inherited_color, inherited_font_size)?;
            }
            VNode::Comment { .. } => {
                // 注释节点不渲染
            }
            VNode::Fragment { children } => {
                // Fragment 只是包装，递归渲染子节点（传递继承的文字样式）
                for child in children {
                    Self::render_recursive(child, renderer, parent_x, parent_y, inherited_color, inherited_font_size)?;
                }
            }
        }

        Ok(())
    }

    /// 渲染背景（支持纯色和渐变）
    fn render_background(
        styles: &iris_layout::style::ComputedStyles,
        x: f32,
        y: f32,
        width: f32,
        height: f32,
        renderer: &mut BatchRenderer,
    ) -> Result<(), String> {
        // 尝试获取 background 或 background-color
        let bg_css = styles.get("background")
            .or_else(|| styles.get("background-color"));

        if let Some(bg_value) = bg_css {
            match Self::parse_background(bg_value) {
                Some(Background::Solid(color)) => {
                    if color[3] > 0.0 {
                        renderer.submit(DrawCommand::Rect {
                            x,
                            y,
                            width,
                            height,
                            color,
                            z_index: 0,
                        });
                    }
                }
                Some(Background::Gradient { gradient_type, stops }) => {
                    if stops.len() >= 2 {
                        match gradient_type {
                            GradientType::Linear { horizontal, reverse } => {
                                let (start_color, end_color) = if reverse {
                                    (stops[stops.len() - 1].color, stops[0].color)
                                } else {
                                    (stops[0].color, stops[stops.len() - 1].color)
                                };
                                
                                renderer.submit(DrawCommand::GradientRect {
                                    x,
                                    y,
                                    width,
                                    height,
                                    start_color,
                                    end_color,
                                    horizontal,
                                    position_x: 0.0,
                                    position_y: 0.0,
                                    z_index: 0,
                                });
                            }
                            GradientType::Radial { center_x: _center_x, center_y: _center_y, radius: _radius } => {
                                // 径向渐变暂时使用第一个颜色作为纯色
                                if !stops.is_empty() {
                                    renderer.submit(DrawCommand::Rect {
                                        x,
                                        y,
                                        width,
                                        height,
                                        color: stops[0].color,
                                        z_index: 0,
                                    });
                                }
                            }
                        }
                    }
                }
                None => {}
            }
        }

        Ok(())
    }

    /// 解析 CSS 背景值
    fn parse_background(css: &str) -> Option<Background> {
        let css = css.trim();
        
        // 检查是否是渐变
        if css.starts_with("linear-gradient") {
            return parse_linear_gradient(css);
        }
        
        // 否则尝试解析为纯色
        parse_css_color(css).map(Background::Solid)
    }

    /// 解析线性渐变
    fn parse_linear_gradient(css: &str) -> Option<Background> {
        crate::css_utils::parse_linear_gradient(css)
    }

    /// 解析渐变方向
    fn parse_gradient_direction(dir: &str) -> (bool, bool, usize) {
        crate::css_utils::parse_gradient_direction(dir)
    }

    /// 渲染边框
    fn render_border(
        styles: &iris_layout::style::ComputedStyles,
        x: f32,
        y: f32,
        width: f32,
        height: f32,
        renderer: &mut BatchRenderer,
    ) -> Result<(), String> {
        if let Some(border) = Self::parse_border(styles) {
            renderer.submit(DrawCommand::Border {
                x,
                y,
                width,
                height,
                border_width: border.width,
                border_color: border.color,
                z_index: 0,
            });
        }
        
        Ok(())
    }

    /// 解析 CSS border 属性
    fn parse_border(styles: &iris_layout::style::ComputedStyles) -> Option<BorderInfo> {
        // 获取 border-width
        let width_str = styles.get("border-width")?;
        let width = crate::css_utils::parse_border_width(width_str);
        
        // 检查是否有任何边框宽度 > 0
        if width.0 == 0.0 && width.1 == 0.0 && width.2 == 0.0 && width.3 == 0.0 {
            return None;
        }
        
        // 获取 border-color
        let color_str = styles.get("border-color")
            .or_else(|| styles.get("border")); //  fallback to border shorthand
        
        let color = if let Some(color_css) = color_str {
            crate::css_utils::parse_css_color(color_css).unwrap_or([0.0, 0.0, 0.0, 1.0]) // 默认黑色
        } else {
            [0.0, 0.0, 0.0, 1.0] // 默认黑色
        };
        
        Some(BorderInfo { width, color })
    }

    /// 解析 CSS transition 属性
    fn parse_transition(styles: &iris_layout::style::ComputedStyles) -> Option<AnimationType> {
        let transition = styles.get("transition")?;
        
        // 解析格式: "property duration easing"
        // 例如: "opacity 0.3s ease"
        let parts: Vec<&str> = transition.split_whitespace().collect();
        if parts.len() < 2 {
            return None;
        }
        
        let property = parts[0].to_string();
        let duration_str = parts[1].trim_end_matches('s');
        let duration: f32 = duration_str.parse().unwrap_or(0.3);
        
        let easing = if parts.len() > 2 {
            match parts[2] {
                "ease" => EasingFunction::Ease,
                "ease-in" => EasingFunction::EaseIn,
                "ease-out" => EasingFunction::EaseOut,
                "ease-in-out" => EasingFunction::EaseInOut,
                _ => EasingFunction::Linear,
            }
        } else {
            EasingFunction::Ease
        };
        
        Some(AnimationType::Transition {
            property,
            duration,
            easing,
        })
    }

    /// 更新动画状态
    fn update_animation(
        state: &mut AnimationState,
        delta_time: f32, // 秒
    ) {
        if !state.is_running {
            return;
        }
        
        match &state.animation {
            AnimationType::Transition { duration, easing, .. } => {
                state.progress += delta_time / duration;
                
                if state.progress >= 1.0 {
                    state.progress = 1.0;
                    state.current_value = state.end_value;
                    state.is_running = false;
                } else {
                    let eased_progress = easing.apply(state.progress);
                    state.current_value = state.start_value 
                        + (state.end_value - state.start_value) * eased_progress;
                }
            }
            AnimationType::Keyframes { duration, iteration_count, .. } => {
                state.progress += delta_time / duration;
                
                if *iteration_count > 0.0 && state.progress >= *iteration_count {
                    state.progress = 1.0;
                    state.is_running = false;
                } else if *iteration_count < 0.0 {
                    // 无限循环，重置进度
                    state.progress %= 1.0;
                } else {
                    state.progress %= *iteration_count;
                }
                
                // 简化的关键帧插值 (实际需要解析 @keyframes)
                state.current_value = state.start_value 
                    + (state.end_value - state.start_value) * state.progress;
            }
        }
    }

    /// 渲染文本节点（使用继承的文字颜色和字号）
    fn render_text(
        content: &str,
        x: f32,
        y: f32,
        renderer: &mut BatchRenderer,
        inherited_color: [f32; 4],
        inherited_font_size: f32,
    ) -> Result<(), String> {
        let text = content.trim();
        if text.is_empty() {
            return Ok(());
        }
        
        // 计算文本宽度：区分ASCII和非ASCII字符
        let width = Self::calculate_text_width(text, inherited_font_size);
        
        renderer.submit(DrawCommand::Text {
            x,
            y,
            width,
            height: inherited_font_size,
            text: text.to_string(),
            color: inherited_color,
            font_size: inherited_font_size,
            bold: false,
            z_index: 0,
        });
        
        debug!(
            content = text,
            x,
            y,
            font_size = inherited_font_size,
            color = ?inherited_color,
            width,
            "Rendered text with font atlas"
        );
        
        Ok(())
    }
    
    /// 计算文本宽度（像素）
    /// 
    /// ASCII字符按0.6em计算，非ASCII字符（中文等）按1.0em计算
    fn calculate_text_width(text: &str, font_size: f32) -> f32 {
        text.chars()
            .map(|c| {
                let ratio = if c.is_ascii() { 0.6 } else { 1.0 };
                font_size * ratio
            })
            .sum()
    }

    /// 解析文本信息
    fn parse_text(content: &str, x: f32, y: f32) -> Option<TextInfo> {
        // 简化实现：使用默认字体大小和颜色
        // 后续将从 VNode 的样式中提取这些信息
        Some(TextInfo {
            content: content.to_string(),
            font_size: 16.0, // 默认 16px
            color: [0.0, 0.0, 0.0, 1.0], // 默认黑色
            x,
            y,
        })
    }
    fn parse_background_color(styles: &iris_layout::style::ComputedStyles) -> [f32; 4] {
        // 尝试解析 background-color 属性
        if let Some(color_str) = styles.get("background-color") {
            crate::css_utils::parse_css_color(color_str).unwrap_or([0.0, 0.0, 0.0, 0.0])
        } else {
            [0.0, 0.0, 0.0, 0.0] // 透明
        }
    }

    /// 获取元素的可见性
    fn is_visible(styles: &iris_layout::style::ComputedStyles) -> bool {
        // 检查 display 属性
        if let Some(display) = styles.get("display") {
            if display == "none" {
                return false;
            }
        }
        
        // 检查 visibility 属性
        if let Some(visibility) = styles.get("visibility") {
            if visibility == "hidden" {
                return false;
            }
        }

        true
    }
}

/// 渲染统计信息
#[derive(Debug, Default)]
pub struct RenderStats {
    /// 绘制的元素数量
    pub elements_drawn: usize,
    /// 跳过的元素数量
    pub elements_skipped: usize,
    /// 文本节点数量
    pub text_nodes: usize,
    /// 总节点数
    pub total_nodes: usize,
}

impl RenderStats {
    /// 从 VNode 树收集统计信息
    pub fn collect(vnode: &VNode) -> Self {
        let mut stats = Self::default();
        Self::collect_recursive(vnode, &mut stats);
        stats
    }

    fn collect_recursive(vnode: &VNode, stats: &mut RenderStats) {
        stats.total_nodes += 1;

        match vnode {
            VNode::Element {
                layout, children, ..
            } => {
                if layout.is_some() {
                    stats.elements_drawn += 1;
                } else {
                    stats.elements_skipped += 1;
                }
                
                for child in children {
                    Self::collect_recursive(child, stats);
                }
            }
            VNode::Text { .. } => {
                stats.text_nodes += 1;
            }
            VNode::Comment { .. } => {
                // 注释节点不计入
            }
            VNode::Fragment { children } => {
                // Fragment 本身不计入 total_nodes
                stats.total_nodes -= 1;
                for child in children {
                    Self::collect_recursive(child, stats);
                }
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[cfg(feature = "vue-sfc")]
    use iris_dom::vnode::VNode;
    use iris_layout::layout::LayoutBox;
    use iris_layout::style::ComputedStyles;

    #[test]
    fn test_collect_stats() {
        let mut vnode = VNode::element("div");
        vnode.append_child(VNode::text("Hello"));
        vnode.append_child(VNode::element("span"));

        let stats = RenderStats::collect(&vnode);
        assert_eq!(stats.total_nodes, 3);
        assert_eq!(stats.text_nodes, 1);
    }

    #[test]
    fn test_fragment_rendering() {
        let fragment = VNode::fragment(vec![
            VNode::element("div"),
            VNode::element("span"),
        ]);

        let stats = RenderStats::collect(&fragment);
        // Fragment 本身不计入，但子节点计入
        assert_eq!(stats.total_nodes, 2);
        assert_eq!(stats.elements_drawn, 0); // 没有布局信息
        assert_eq!(stats.elements_skipped, 2);
    }

    #[test]
    fn test_parse_css_color_rgba() {
        let color = crate::css_utils::parse_css_color("rgba(255, 128, 64, 0.5)");
        assert!(color.is_some());
        let color = color.unwrap();
        assert!((color[0] - 1.0).abs() < 0.01); // 255/255 = 1.0
        assert!((color[1] - 0.502).abs() < 0.01); // 128/255 ≈ 0.502
        assert!((color[2] - 0.251).abs() < 0.01); // 64/255 ≈ 0.251
        assert!((color[3] - 0.5).abs() < 0.01);
    }

    #[test]
    fn test_parse_css_color_invalid() {
        let color = crate::css_utils::parse_css_color("invalid");
        assert!(color.is_none());
    }

    #[test]
    fn test_parse_css_color_partial() {
        let color = crate::css_utils::parse_css_color("rgba(255, 0, 0");
        assert!(color.is_none()); // 不完整，返回 None
    }

    #[test]
    fn test_element_with_layout() {
        let mut vnode = VNode::element("div");
        
        // 设置样式和布局信息（模拟）
        if let VNode::Element { ref mut styles, ref mut layout, .. } = vnode {
            styles.set("background-color", "rgba(255, 0, 0, 1)");
            *layout = Some(LayoutBox::with_position(0.0, 0.0, 100.0, 50.0));
        }

        let stats = RenderStats::collect(&vnode);
        assert_eq!(stats.elements_drawn, 1);
        assert_eq!(stats.elements_skipped, 0);
    }

    #[test]
    fn test_zero_size_element() {
        let mut vnode = VNode::element("div");
        
        if let VNode::Element { ref mut layout, .. } = vnode {
            *layout = Some(LayoutBox::with_position(0.0, 0.0, 0.0, 0.0));
        }

        let stats = RenderStats::collect(&vnode);
        assert_eq!(stats.elements_drawn, 1); // 有布局信息就算 drawn
    }

    #[test]
    fn test_nested_elements() {
        let mut parent = VNode::element("div");
        if let VNode::Element { ref mut layout, .. } = parent {
            *layout = Some(LayoutBox::with_position(0.0, 0.0, 200.0, 100.0));
        }

        let mut child = VNode::element("span");
        if let VNode::Element { ref mut layout, .. } = child {
            *layout = Some(LayoutBox::with_position(10.0, 10.0, 50.0, 30.0));
        }

        parent.append_child(child);

        let stats = RenderStats::collect(&parent);
        assert_eq!(stats.total_nodes, 2);
        assert_eq!(stats.elements_drawn, 2);
    }

    #[test]
    fn test_comment_not_counted() {
        let mut vnode = VNode::element("div");
        vnode.append_child(VNode::comment("This is a comment"));

        let stats = RenderStats::collect(&vnode);
        // div + comment (注释计入 total_nodes 但不计入其他统计)
        assert_eq!(stats.total_nodes, 2);
    }

    #[test]
    fn test_mixed_content() {
        let mut div = VNode::element("div");
        div.append_child(VNode::text("Hello"));
        div.append_child(VNode::element("span"));
        div.append_child(VNode::comment("comment"));

        let stats = RenderStats::collect(&div);
        // div + text + span + comment = 4
        assert_eq!(stats.total_nodes, 4);
        assert_eq!(stats.text_nodes, 1);
        assert_eq!(stats.elements_skipped, 2); // div 和 span 都没有布局
    }

    #[test]
    fn test_deep_nesting() {
        fn create_nested(depth: u32) -> VNode {
            if depth == 0 {
                VNode::element("leaf")
            } else {
                let mut parent = VNode::element("parent");
                parent.append_child(create_nested(depth - 1));
                parent
            }
        }

        let vnode = create_nested(5);
        let stats = RenderStats::collect(&vnode);
        assert_eq!(stats.total_nodes, 6); // 5 parents + 1 leaf
        assert_eq!(stats.elements_skipped, 6);
    }

    #[test]
    fn test_is_visible_display_none() {
        let mut styles = ComputedStyles::new();
        styles.set("display", "none");
        assert!(!VNodeRenderer::is_visible(&styles));
    }

    #[test]
    fn test_is_visible_hidden() {
        let mut styles = ComputedStyles::new();
        styles.set("visibility", "hidden");
        assert!(!VNodeRenderer::is_visible(&styles));
    }

    #[test]
    fn test_is_visible_normal() {
        let styles = ComputedStyles::new();
        assert!(VNodeRenderer::is_visible(&styles));
    }

    #[test]
    fn test_parse_linear_gradient_horizontal() {
        let bg = VNodeRenderer::parse_background("linear-gradient(to right, red, blue)");
        assert!(bg.is_some());
        match bg.unwrap() {
            Background::Gradient { gradient_type, stops } => {
                match gradient_type {
                    GradientType::Linear { horizontal, .. } => {
                        assert!(horizontal); // to right = 水平
                    }
                }
                assert_eq!(stops.len(), 2);
            }
            _ => panic!("Expected gradient"),
        }
    }

    #[test]
    fn test_parse_linear_gradient_vertical() {
        let bg = VNodeRenderer::parse_background("linear-gradient(to bottom, red, blue)");
        assert!(bg.is_some());
        match bg.unwrap() {
            Background::Gradient { gradient_type, stops } => {
                match gradient_type {
                    GradientType::Linear { horizontal, .. } => {
                        assert!(!horizontal); // to bottom = 垂直
                    }
                }
                assert_eq!(stops.len(), 2);
            }
            _ => panic!("Expected gradient"),
        }
    }

    #[test]
    fn test_parse_solid_color() {
        let bg = VNodeRenderer::parse_background("rgba(255, 0, 0, 1)");
        assert!(bg.is_some());
        match bg.unwrap() {
            Background::Solid(color) => {
                assert!((color[0] - 1.0).abs() < 0.01);
            }
            _ => panic!("Expected solid color"),
        }
    }

    #[test]
    fn test_parse_invalid_gradient() {
        let bg = VNodeRenderer::parse_background("linear-gradient(red)");
        assert!(bg.is_none()); // 至少需要2个颜色
    }

    #[test]
    fn test_parse_border_single() {
        let mut styles = ComputedStyles::new();
        styles.set("border-width", "2px");
        styles.set("border-color", "red");
        
        let border = VNodeRenderer::parse_border(&styles);
        assert!(border.is_some());
        let border = border.unwrap();
        assert_eq!(border.width, (2.0, 2.0, 2.0, 2.0));
        assert!((border.color[0] - 1.0).abs() < 0.01); // red
    }

    #[test]
    fn test_parse_border_four_values() {
        let mut styles = ComputedStyles::new();
        styles.set("border-width", "1px 2px 3px 4px");
        styles.set("border-color", "blue");
        
        let border = VNodeRenderer::parse_border(&styles);
        assert!(border.is_some());
        let border = border.unwrap();
        assert_eq!(border.width, (1.0, 2.0, 3.0, 4.0));
        assert!((border.color[2] - 1.0).abs() < 0.01); // blue
    }

    #[test]
    fn test_parse_border_two_values() {
        let mut styles = ComputedStyles::new();
        styles.set("border-width", "5px 10px");
        
        let border = VNodeRenderer::parse_border(&styles);
        assert!(border.is_some());
        let border = border.unwrap();
        assert_eq!(border.width, (5.0, 10.0, 5.0, 10.0));
    }

    #[test]
    fn test_parse_border_three_values() {
        let mut styles = ComputedStyles::new();
        styles.set("border-width", "1px 2px 3px");
        
        let border = VNodeRenderer::parse_border(&styles);
        assert!(border.is_some());
        let border = border.unwrap();
        assert_eq!(border.width, (1.0, 2.0, 3.0, 2.0));
    }

    #[test]
    fn test_parse_border_no_width() {
        let styles = ComputedStyles::new();
        let border = VNodeRenderer::parse_border(&styles);
        assert!(border.is_none());
    }

    #[test]
    fn test_parse_border_zero_width() {
        let mut styles = ComputedStyles::new();
        styles.set("border-width", "0px");
        
        let border = VNodeRenderer::parse_border(&styles);
        assert!(border.is_none());
    }

    #[test]
    fn test_ease_linear() {
        assert!((EasingFunction::Linear.apply(0.5) - 0.5).abs() < 0.01);
        assert!((EasingFunction::Linear.apply(0.0) - 0.0).abs() < 0.01);
        assert!((EasingFunction::Linear.apply(1.0) - 1.0).abs() < 0.01);
    }

    #[test]
    fn test_ease_in() {
        // ease-in 在 0.5 时应该 < 0.5 (慢开始)
        let value = EasingFunction::EaseIn.apply(0.5);
        assert!(value < 0.5);
        assert!((value - 0.125).abs() < 0.01); // t^3 = 0.125
    }

    #[test]
    fn test_ease_out() {
        // ease-out 在 0.5 时应该 > 0.5 (怏结束)
        let value = EasingFunction::EaseOut.apply(0.5);
        assert!(value > 0.5);
        assert!((value - 0.875).abs() < 0.01); // (t-1)^3+1 = 0.875
    }

    #[test]
    fn test_parse_transition() {
        let mut styles = ComputedStyles::new();
        styles.set("transition", "opacity 0.3s ease");
        
        let animation = VNodeRenderer::parse_transition(&styles);
        assert!(animation.is_some());
        
        if let Some(AnimationType::Transition { property, duration, easing }) = animation {
            assert_eq!(property, "opacity");
            assert!((duration - 0.3).abs() < 0.01);
            assert!(matches!(easing, EasingFunction::Ease));
        } else {
            panic!("Expected Transition animation type");
        }
    }

    #[test]
    fn test_parse_transition_linear() {
        let mut styles = ComputedStyles::new();
        styles.set("transition", "width 0.5s linear");
        
        let animation = VNodeRenderer::parse_transition(&styles);
        assert!(animation.is_some());
        
        if let Some(AnimationType::Transition { property, duration, easing }) = animation {
            assert_eq!(property, "width");
            assert!((duration - 0.5).abs() < 0.01);
            assert!(matches!(easing, EasingFunction::Linear));
        } else {
            panic!("Expected Transition animation type");
        }
    }

    #[test]
    fn test_update_animation_transition() {
        let mut state = AnimationState {
            animation: AnimationType::Transition {
                property: "opacity".to_string(),
                duration: 1.0,
                easing: EasingFunction::Linear,
            },
            start_value: 0.0,
            end_value: 1.0,
            current_value: 0.0,
            progress: 0.0,
            is_running: true,
        };
        
        // 更新 0.5 秒
        VNodeRenderer::update_animation(&mut state, 0.5);
        assert!((state.progress - 0.5).abs() < 0.01);
        assert!((state.current_value - 0.5).abs() < 0.01);
        assert!(state.is_running);
        
        // 再更新 0.5 秒 (完成)
        VNodeRenderer::update_animation(&mut state, 0.5);
        assert!((state.progress - 1.0).abs() < 0.01);
        assert!((state.current_value - 1.0).abs() < 0.01);
        assert!(!state.is_running);
    }

    #[test]
    fn test_parse_text_basic() {
        let text_info = VNodeRenderer::parse_text("Hello", 10.0, 20.0);
        assert!(text_info.is_some());
        let text_info = text_info.unwrap();
        assert_eq!(text_info.content, "Hello");
        assert!((text_info.font_size - 16.0).abs() < 0.01);
        assert!((text_info.x - 10.0).abs() < 0.01);
        assert!((text_info.y - 20.0).abs() < 0.01);
    }

    #[test]
    fn test_parse_text_empty() {
        let text_info = VNodeRenderer::parse_text("", 0.0, 0.0);
        assert!(text_info.is_some());
        assert_eq!(text_info.unwrap().content, "");
    }

    #[test]
    fn test_parse_text_chinese() {
        let text_info = VNodeRenderer::parse_text("你好世界", 0.0, 0.0);
        assert!(text_info.is_some());
        assert_eq!(text_info.unwrap().content, "你好世界");
    }

    #[test]
    fn test_text_node_rendering() {
        // 创建包含文本的 VNode
        let mut div = VNode::element("div");
        div.append_child(VNode::text("Hello World"));
        
        let stats = RenderStats::collect(&div);
        assert_eq!(stats.total_nodes, 2);
        assert_eq!(stats.text_nodes, 1);
    }
}
