use takumi::prelude::{Length::*, *};

use crate::test_utils::run_fixture_test;

#[test]
fn text_inline() {
  let texts = &[
    (
      "The quick brown fox jumps over the lazy dog.",
      Style::default()
        .with(StyleDeclaration::display(Display::Flex))
        .with(StyleDeclaration::display(Display::Inline)),
    ),
    (
      "Lorem ipsum dolor sit amet, consectetur adipiscing elit. ",
      Style::default()
        .with(StyleDeclaration::display(Display::Flex))
        .with(StyleDeclaration::text_transform(TextTransform::Uppercase))
        .with(StyleDeclaration::display(Display::Inline)),
    ),
    (
      "Nothing beats a jet2 holiday! ",
      Style::default()
        .with(StyleDeclaration::display(Display::Flex))
        .with(StyleDeclaration::color(ColorInput::Value(Color([
          255, 0, 0, 255,
        ]))))
        .with(StyleDeclaration::display(Display::Inline)),
    ),
    (
      "I'm making a browser at this point. ",
      Style::default()
        .with(StyleDeclaration::display(Display::Flex))
        .with(StyleDeclaration::font_weight(FontWeight::from(600.0)))
        .with(StyleDeclaration::display(Display::Inline))
        .with(StyleDeclaration::color(ColorInput::Value(Color([
          0, 0, 255, 255,
        ]))))
        .with(StyleDeclaration::font_style(FontStyle::italic())),
    ),
  ];

  let children: Vec<Node> = texts
    .iter()
    .map(|(text, style)| Node::text(text.to_string()).with_style(style.clone()))
    .collect();

  let container = Node::container(children).with_style(
    Style::default()
      .with(StyleDeclaration::display(Display::Flex))
      .with(StyleDeclaration::background_color(ColorInput::Value(
        Color::white(),
      )))
      .with(StyleDeclaration::width(Percentage(100.0)))
      .with(StyleDeclaration::display(Display::Block))
      .with(StyleDeclaration::justify_content(JustifyContent::Center))
      .with_line_clamp(3u32.into())
      .with(StyleDeclaration::text_overflow(TextOverflow::Ellipsis))
      .with(StyleDeclaration::font_size(Px(48.0).into()))
      .with_white_space(WhiteSpace::pre_wrap()),
  );

  run_fixture_test(container, "text_inline");
}

#[test]
fn inline_image() {
  // Inline image should behave as inline-level box content
  let children: Vec<Node> = vec![
    Node::text("Before ".to_string())
      .with_style(Style::default().with(StyleDeclaration::display(Display::Inline))),
    Node::image(("assets/images/yeecord.png", 64.0, 64.0)).with_style(
      Style::default()
        .with(StyleDeclaration::display(Display::Inline))
        .with_border_width(Sides([Px(12.0).into(); 4]))
        .with_border_style(Sides([BorderStyle::Solid; 4]))
        .with_border_color(Sides([ColorInput::Value(Color::transparent()); 4]))
        .with(StyleDeclaration::background_image(
          BackgroundImages::from_css_str("linear-gradient(to right, red, blue)").ok(),
        ))
        .with(StyleDeclaration::background_clip(
          BackgroundClip::BorderArea,
        )),
    ),
    Node::text(" After".to_string())
      .with_style(Style::default().with(StyleDeclaration::display(Display::Inline))),
  ];

  let container = Node::container([Node::container(children).with_style(
    Style::default()
      .with(StyleDeclaration::display(Display::Flex))
      .with_border_width(Sides([Px(2.0).into(); 4]))
      .with_border_style(Sides([BorderStyle::Solid; 4]))
      .with(StyleDeclaration::display(Display::Block))
      .with(StyleDeclaration::font_size(Px(48.0).into())),
  )])
  .with_style(
    Style::default()
      .with(StyleDeclaration::display(Display::Flex))
      .with(StyleDeclaration::width(Percentage(100.0)))
      .with(StyleDeclaration::height(Percentage(100.0)))
      .with(StyleDeclaration::align_items(AlignItems::Center))
      .with(StyleDeclaration::justify_content(JustifyContent::Center))
      .with(StyleDeclaration::background_color(ColorInput::Value(
        Color::white(),
      )))
      .with_white_space(WhiteSpace::pre()),
  );

  run_fixture_test(container, "inline_image");
}

#[test]
fn inline_image_em_regression() {
  let children: Vec<Node> = vec![
    Node::text("hello ".to_string())
      .with_style(Style::default().with(StyleDeclaration::display(Display::Inline))),
    Node::image(("assets/images/yeecord.png", 64.0, 64.0)).with_style(
      Style::default()
        .with(StyleDeclaration::display(Display::InlineBlock))
        .with(StyleDeclaration::width(Em(1.0)))
        .with(StyleDeclaration::height(Em(1.0)))
        .with(StyleDeclaration::vertical_align(VerticalAlign::Length(Em(
          -0.1,
        )))),
    ),
    Node::text(" world".to_string())
      .with_style(Style::default().with(StyleDeclaration::display(Display::Inline))),
  ];

  let container = Node::container(children).with_style(
    Style::default()
      .with(StyleDeclaration::display(Display::Block))
      .with(StyleDeclaration::width(Percentage(100.0)))
      .with(StyleDeclaration::height(Percentage(100.0)))
      .with(StyleDeclaration::background_color(ColorInput::Value(
        Color::white(),
      )))
      .with(StyleDeclaration::font_size(Px(64.0).into())),
  );

  run_fixture_test(container, "inline_image_em_regression");
}

#[test]
fn inline_float_wrap() {
  let node = Node::container([
    Node::image("assets/images/yeecord.png").with_style(
      Style::default()
        .with(StyleDeclaration::display(Display::Inline))
        .with(StyleDeclaration::float(Float::Left))
        .with(StyleDeclaration::width(Px(144.0)))
        .with(StyleDeclaration::height(Px(144.0)))
        .with_margin(Sides([Px(0.0), Px(20.0), Px(12.0), Px(0.0)]))
        .with_border_radius(BorderRadius(Sides([SpacePair::from_single(Px(20.0)); 4]))),
    ),
    Node::container([
      Node::text("Float Card".to_string()).with_style(
        Style::default()
          .with(StyleDeclaration::display(Display::Block))
          .with(StyleDeclaration::font_size(Px(20.0).into()))
          .with(StyleDeclaration::font_weight(FontWeight::from(700.0)))
          .with(StyleDeclaration::color(ColorInput::Value(Color::white()))),
      ),
      Node::text("A floated inline-block container should keep participating in inline layout and push adjacent text away until its bottom edge.".to_string()).with_style(
        Style::default()
          .with(StyleDeclaration::display(Display::Block))
          .with(StyleDeclaration::font_size(Px(15.0).into()))
          .with(StyleDeclaration::line_height(LineHeight::Unitless(1.35)))
          .with(StyleDeclaration::color(ColorInput::Value(Color([231, 239, 255, 255])))),
      ),
    ])
    .with_style(
      Style::default()
        .with(StyleDeclaration::display(Display::InlineBlock))
        .with(StyleDeclaration::float(Float::Right))
        .with(StyleDeclaration::width(Px(220.0)))
        .with_margin(Sides([Px(0.0), Px(0.0), Px(12.0), Px(20.0)]))
        .with_padding(Sides([Px(16.0); 4]))
        .with(StyleDeclaration::background_color(ColorInput::Value(Color([
          31, 64, 122, 255,
        ]))))
        .with_border_radius(BorderRadius(Sides([SpacePair::from_single(Px(18.0)); 4]))),
    ),
    Node::text(
      "Parley 0.9 adds caller-controlled line geometry so Takumi can place floats during line breaking instead of merely recording out-of-flow boxes. This fixture checks that the first lines narrow between the left image and the right card, then expand back to the full measure width after both floated boxes end. The text should read naturally, with no overlap and no duplicated boxes in the measured or painted output."
        .to_string(),
    )
    .with_style(Style::default().with(StyleDeclaration::display(Display::Inline))),
  ])
  .with_style(
    Style::default()
      .with(StyleDeclaration::display(Display::Block))
      .with(StyleDeclaration::width(Px(920.0)))
      .with(StyleDeclaration::background_color(ColorInput::Value(Color([
        248, 250, 252, 255,
      ]))))
      .with_padding(Sides([Px(28.0); 4]))
      .with(StyleDeclaration::font_size(Px(30.0).into()))
      .with(StyleDeclaration::line_height(LineHeight::Unitless(1.25)))
      .with(StyleDeclaration::color(ColorInput::Value(Color([
        24, 34, 53, 255,
      ])))),
  );

  run_fixture_test(node, "inline_float_wrap");
}

#[test]
fn inline_block_in_inline() {
  // A block-level container inside inline content: should create anonymous block formatting context
  let children: Vec<Node> = vec![
    Node::text("Start ".to_string())
      .with_style(Style::default().with(StyleDeclaration::display(Display::Inline))),
    Node::container([Node::text("Block inside inline".to_string())
      .with_style(Style::default().with(StyleDeclaration::display(Display::Block)))])
    .with_style(
      Style::default()
        .with(StyleDeclaration::display(Display::Block))
        .with(StyleDeclaration::background_color(ColorInput::Value(
          Color([200, 200, 255, 255]),
        )))
        .with(StyleDeclaration::width(Percentage(80.0)))
        .with(StyleDeclaration::font_size(Px(18.0).into())),
    ),
    Node::text(" End".to_string())
      .with_style(Style::default().with(StyleDeclaration::display(Display::Inline))),
  ];

  let container = Node::container(children.into_boxed_slice()).with_style(
    Style::default()
      .with(StyleDeclaration::display(Display::Flex))
      .with(StyleDeclaration::background_color(ColorInput::Value(
        Color::white(),
      )))
      .with(StyleDeclaration::width(Percentage(100.0)))
      .with(StyleDeclaration::display(Display::Block))
      .with(StyleDeclaration::font_size(Px(24.0).into()))
      .with_white_space(WhiteSpace::pre()),
  );

  run_fixture_test(container, "inline_block_in_inline");
}

#[test]
fn inline_span_background_color() {
  let texts = &[
    (
      "Hello ",
      Style::default()
        .with(StyleDeclaration::display(Display::Flex))
        .with(StyleDeclaration::background_color(ColorInput::Value(
          Color([255, 200, 200, 255]),
        )))
        .with(StyleDeclaration::display(Display::Inline)),
    ),
    (
      "world ",
      Style::default()
        .with(StyleDeclaration::display(Display::Flex))
        .with(StyleDeclaration::background_color(ColorInput::Value(
          Color([200, 255, 200, 255]),
        )))
        .with(StyleDeclaration::display(Display::Inline)),
    ),
    (
      "from ",
      Style::default()
        .with(StyleDeclaration::display(Display::Flex))
        .with(StyleDeclaration::background_color(ColorInput::Value(
          Color([200, 200, 255, 255]),
        )))
        .with(StyleDeclaration::display(Display::Inline)),
    ),
    (
      "Takumi!",
      Style::default()
        .with(StyleDeclaration::display(Display::Flex))
        .with(StyleDeclaration::background_color(ColorInput::Value(
          Color([255, 255, 200, 255]),
        )))
        .with(StyleDeclaration::display(Display::Inline)),
    ),
  ];

  let children: Vec<Node> = texts
    .iter()
    .map(|(text, style)| Node::text(text.to_string()).with_style(style.clone()))
    .collect();

  let container = Node::container(children).with_style(
    Style::default()
      .with(StyleDeclaration::display(Display::Flex))
      .with(StyleDeclaration::width(Percentage(100.0)))
      .with(StyleDeclaration::height(Percentage(100.0)))
      .with(StyleDeclaration::align_items(AlignItems::Center))
      .with(StyleDeclaration::justify_content(JustifyContent::Center))
      .with(StyleDeclaration::background_color(ColorInput::Value(
        Color::white(),
      )))
      .with_white_space(WhiteSpace::pre())
      .with(StyleDeclaration::font_size(Px(48.0).into())),
  );

  run_fixture_test(container, "inline_span_background_color");
}

#[test]
fn inline_outline_span_boundaries() {
  let children: Vec<Node> = vec![
    Node::text("STEAM ".to_string())
      .with_style(Style::default().with(StyleDeclaration::display(Display::Inline)))
      ,
    Node::text(
        "education can become accessible through a sequence of free and high-quality teaching examples"
          .to_string(),
      )
      .with_style(
        Style::default()
          .with(StyleDeclaration::display(Display::Inline))
          .with(StyleDeclaration::outline_width(Px(3.0).into()))
          .with(StyleDeclaration::outline_style(BorderStyle::Solid))
          .with(StyleDeclaration::outline_color(ColorInput::Value(Color([
            255, 0, 0, 255,
          ])))),
      )
      ,
    Node::text(" for everyone.".to_string())
      .with_style(Style::default().with(StyleDeclaration::display(Display::Inline)))
      ,
  ];

  let container = Node::container([Node::container(children).with_style(
    Style::default()
      .with(StyleDeclaration::display(Display::Flex))
      .with(StyleDeclaration::display(Display::Block))
      .with(StyleDeclaration::width(Px(320.0)))
      .with_padding(Sides([Px(24.0); 4]))
      .with_border_width(Sides([Px(2.0).into(); 4]))
      .with_border_style(Sides([BorderStyle::Solid; 4]))
      .with(StyleDeclaration::font_size(Px(28.0).into()))
      .with(StyleDeclaration::line_height(Px(34.0).into()))
      .with(StyleDeclaration::background_color(ColorInput::Value(
        Color::white(),
      ))),
  )])
  .with_style(
    Style::default()
      .with(StyleDeclaration::display(Display::Flex))
      .with(StyleDeclaration::width(Percentage(100.0)))
      .with(StyleDeclaration::height(Percentage(100.0)))
      .with(StyleDeclaration::align_items(AlignItems::Center))
      .with(StyleDeclaration::justify_content(JustifyContent::Center))
      .with(StyleDeclaration::background_color(ColorInput::Value(
        Color([240, 240, 240, 255]),
      ))),
  );

  run_fixture_test(container, "inline_outline_span_boundaries");
}

#[test]
fn inline_atomic_containers() {
  let atomic = |display, bg_color, border_color, label: &str| -> Node {
    Node::container([Node::text(label.to_string())]).with_style(
      Style::default()
        .with(StyleDeclaration::display(Display::Flex))
        .with(StyleDeclaration::display(display))
        .with_padding(Sides([Px(8.0); 4]))
        .with(StyleDeclaration::background_color(ColorInput::Value(
          bg_color,
        )))
        .with_border_width(Sides([Px(5.0).into(); 4]))
        .with_border_style(Sides([BorderStyle::Solid; 4]))
        .with_border_color(Sides([ColorInput::Value(border_color); 4])),
    )
  };

  let container = Node::container([Node::container([
    Node::text("before ".to_string()).with_style(
      Style::default()
        .with(StyleDeclaration::display(Display::Flex))
        .with(StyleDeclaration::display(Display::Inline)),
    ),
    atomic(
      Display::InlineBlock,
      Color([255, 0, 0, 100]),
      Color([180, 20, 20, 255]),
      "inline-block",
    ),
    Node::text(" mid ".to_string()).with_style(
      Style::default()
        .with(StyleDeclaration::display(Display::Flex))
        .with(StyleDeclaration::display(Display::Inline)),
    ),
    atomic(
      Display::InlineFlex,
      Color([0, 255, 0, 100]),
      Color([20, 140, 20, 255]),
      "inline-flex",
    ),
    Node::text(" end ".to_string()).with_style(
      Style::default()
        .with(StyleDeclaration::display(Display::Flex))
        .with(StyleDeclaration::display(Display::Inline)),
    ),
    atomic(
      Display::InlineGrid,
      Color([0, 0, 255, 100]),
      Color([20, 20, 180, 255]),
      "inline-grid",
    ),
  ])
  .with_style(
    Style::default()
      .with(StyleDeclaration::display(Display::Flex))
      .with(StyleDeclaration::display(Display::Block))
      .with(StyleDeclaration::font_size(Px(24.0).into()))
      .with_border_width(Sides([Px(6.0).into(); 4]))
      .with_border_style(Sides([BorderStyle::Solid; 4]))
      .with_border_color(Sides([ColorInput::Value(Color([40, 40, 40, 255])); 4])),
  )])
  .with_style(
    Style::default()
      .with(StyleDeclaration::display(Display::Flex))
      .with(StyleDeclaration::width(Percentage(100.0)))
      .with(StyleDeclaration::height(Percentage(100.0)))
      .with(StyleDeclaration::align_items(AlignItems::Center))
      .with(StyleDeclaration::justify_content(JustifyContent::Center))
      .with(StyleDeclaration::background_color(ColorInput::Value(
        Color::white(),
      )))
      .with_white_space(WhiteSpace::pre()),
  );

  run_fixture_test(container, "inline_atomic_containers");
}
#[test]
fn inline_nested_flex_block() {
  let inline_flex_children: Vec<Node> = vec![
    Node::text("Flex Start ".to_string())
      .with_style(Style::default().with(StyleDeclaration::display(Display::Inline))),
    Node::container([Node::text("Inner".to_string())]).with_style(
      Style::default()
        .with(StyleDeclaration::display(Display::InlineBlock))
        .with_padding(Sides([Px(4.0); 4]))
        .with_margin(Sides([Px(0.0), Px(10.0), Px(0.0), Px(10.0)]))
        .with(StyleDeclaration::background_color(ColorInput::Value(
          Color([255, 200, 200, 255]),
        ))),
    ),
    Node::text(" Flex End".to_string())
      .with_style(Style::default().with(StyleDeclaration::display(Display::Inline))),
  ];

  let children: Vec<Node> = vec![
    Node::text(
        "This is some preceding text that is long enough to wrap eventually. ".to_string(),
      )
      .with_style(Style::default().with(StyleDeclaration::display(Display::Inline)))
      ,
    Node::container(inline_flex_children)
      .with_style(
        Style::default()
          .with(StyleDeclaration::display(Display::InlineFlex))
          .with(StyleDeclaration::background_color(ColorInput::Value(
            Color([200, 255, 200, 255]),
          )))
          .with_padding(Sides([Px(5.0); 4]))
          .with(StyleDeclaration::align_items(AlignItems::Center))
          .with(StyleDeclaration::vertical_align(VerticalAlign::Keyword(
            VerticalAlignKeyword::Middle,
          ))),
      )
      ,
    Node::text(
        " followed by more text that should definitely wrap and show how the inline-flex container behaves when it is part of a wrapped line. We want to make sure the nested boxes are drawn in the correct positions even after wrapping.".to_string(),
      )
      .with_style(Style::default().with(StyleDeclaration::display(Display::Inline)))
      ,
  ];

  let container = Node::container(children).with_style(
    Style::default()
      .with(StyleDeclaration::display(Display::Flex))
      .with(StyleDeclaration::width(Px(800.0)))
      .with(StyleDeclaration::display(Display::Block))
      .with_padding(Sides([Px(20.0); 4]))
      .with(StyleDeclaration::background_color(ColorInput::Value(
        Color::white(),
      )))
      .with(StyleDeclaration::font_size(Px(20.0).into()))
      .with(StyleDeclaration::line_height(LineHeight::Length(Px(40.0)))),
  );

  run_fixture_test(container, "inline_nested_flex_block");
}

#[test]
fn inline_complex_nested_fixture() {
  let metadata_children: Vec<Node> = vec![
    Node::text("METADATA gyjpq: ".to_string()).with_style(
      Style::default()
        .with(StyleDeclaration::display(Display::Inline))
        .with(StyleDeclaration::font_weight(FontWeight::from(700.0)))
        .with(StyleDeclaration::color(ColorInput::Value(Color([
          10, 34, 57, 255,
        ]))))
        .with(StyleDeclaration::text_transform(TextTransform::Uppercase))
        .with(StyleDeclaration::font_size(Px(20.0).into()))
        .with(StyleDeclaration::background_color(ColorInput::Value(
          Color([208, 230, 248, 255]),
        ))),
    ),
    Node::container([Node::text("Tag".to_string()).with_style(
      Style::default()
        .with(StyleDeclaration::display(Display::Inline))
        .with(StyleDeclaration::color(ColorInput::Value(Color::white())))
        .with(StyleDeclaration::font_size(Px(16.0).into()))
        .with(StyleDeclaration::font_weight(FontWeight::from(600.0))),
    )])
    .with_style(
      Style::default()
        .with(StyleDeclaration::display(Display::InlineFlex))
        .with(StyleDeclaration::align_items(AlignItems::Center))
        .with_gap(SpacePair::from_single(Px(6.0).into()))
        .with(StyleDeclaration::background_color(ColorInput::Value(
          Color([80, 138, 184, 255]),
        )))
        .with_border_radius(BorderRadius(Sides([SpacePair::from_single(Px(999.0)); 4])))
        .with_padding(Sides([Px(4.0), Px(12.0), Px(4.0), Px(12.0)]))
        .with(StyleDeclaration::vertical_align(VerticalAlign::Keyword(
          VerticalAlignKeyword::Baseline,
        ))),
    ),
  ];

  let children: Vec<Node> = vec![
    Node::text("Inline baseline probe (Aa Bb Cc g j p q y 012345): ".to_string())
      .with_style(Style::default().with(StyleDeclaration::display(Display::Inline))),
    Node::container(metadata_children)
      .with_style(
        Style::default()
          .with(StyleDeclaration::display(Display::InlineFlex))
          .with(StyleDeclaration::vertical_align(VerticalAlign::Keyword(
            VerticalAlignKeyword::Middle,
          )))
          .with(StyleDeclaration::background_color(ColorInput::Value(Color([
            231, 241, 250, 255,
          ]))))
          .with_border_width(Sides([Px(2.0).into(); 4]))
          .with_border_style(Sides([BorderStyle::Solid; 4]))
          .with_border_color(Sides([ColorInput::Value(Color([
            156, 189, 217, 255,
          ])); 4]))
          .with_border_radius(BorderRadius(Sides(
            [SpacePair::from_single(Px(6.0)); 4],
          )))
          .with_padding(Sides([Px(12.0), Px(16.0), Px(12.0), Px(16.0)]))
          .with_margin(Sides([Px(0.0), Px(12.0), Px(0.0), Px(12.0)])),
      ),
    Node::text(
        "After the badge, this sentence verifies wrapping around inline boxes with mixed glyph heights and descenders (g j p q y). ".to_string(),
      )
      .with_style(Style::default().with(StyleDeclaration::display(Display::Inline)))
      ,
    Node::container([Node::text("BOTTOM inline-block sample: gyjpq, 12345, and punctuation !? to expose baseline drift.".to_string())
        .with_style(
          Style::default()
            .with(StyleDeclaration::display(Display::Block))
            .with(StyleDeclaration::font_size(Px(16.0).into()))
            .with(StyleDeclaration::line_height(LineHeight::Length(Em(1.2)))),
        )])
      .with_style(
        Style::default()
          .with(StyleDeclaration::display(Display::InlineBlock))
          .with(StyleDeclaration::vertical_align(VerticalAlign::Keyword(
            VerticalAlignKeyword::Bottom,
          )))
          .with(StyleDeclaration::width(Px(180.0)))
          .with(StyleDeclaration::background_color(ColorInput::Value(Color([
            255, 236, 208, 255,
          ]))))
          .with_border_width(Sides([Px(2.0).into(); 4]))
          .with_border_style(Sides([BorderStyle::Solid; 4]))
          .with_border_color(Sides([ColorInput::Value(Color([
            212, 118, 22, 255,
          ])); 4]))
          .with_padding(Sides([Px(14.0); 4]))
          .with_margin(Sides([Px(0.0), Px(8.0), Px(0.0), Px(8.0)])),
      )
      ,
    Node::text(" End marker: compare the last line's baseline to the first line.".to_string())
      .with_style(Style::default().with(StyleDeclaration::display(Display::Inline)))
      ,
  ];

  let node = Node::container(children).with_style(
    Style::default()
      .with(StyleDeclaration::display(Display::Flex))
      .with(StyleDeclaration::display(Display::Block))
      .with(StyleDeclaration::font_size(Px(24.0).into()))
      .with(StyleDeclaration::line_height(LineHeight::Length(Em(1.4))))
      .with(StyleDeclaration::color(ColorInput::Value(Color([
        38, 38, 38, 255,
      ]))))
      .with(StyleDeclaration::background_color(ColorInput::Value(
        Color::white(),
      )))
      .with(StyleDeclaration::width(Px(900.0)))
      .with_padding(Sides([Px(24.0); 4])),
  );

  run_fixture_test(node, "inline_complex_nested_fixture");
}

#[test]
fn inline_text_decorations() {
  let decorated_children: Vec<Node> = vec![
    Node::text("Hello World".to_string()).with_style(
      Style::default()
        .with(StyleDeclaration::display(Display::Inline))
        .with_text_decoration(
          TextDecoration::builder()
            .line(TextDecorationLines::UNDERLINE | TextDecorationLines::LINE_THROUGH)
            .color(ColorInput::Value(Color([0, 0, 255, 255])))
            .thickness(TextDecorationThickness::Length(Px(4.0)))
            .build(),
        ),
    ),
    Node::text("Woah".to_string()).with_style(
      Style::default()
        .with(StyleDeclaration::display(Display::InlineBlock))
        .with(StyleDeclaration::background_color(ColorInput::Value(
          Color([255, 0, 0, 128]),
        )))
        .with(StyleDeclaration::vertical_align(VerticalAlign::Keyword(
          VerticalAlignKeyword::TextBottom,
        ))),
    ),
    Node::container([
      Node::text("It works right".to_string()).with_style(
        Style::default()
          .with(StyleDeclaration::display(Display::InlineBlock))
          .with(StyleDeclaration::background_color(ColorInput::Value(
            Color([255, 255, 0, 255]),
          ))),
      ),
      Node::text("A flexbox!".to_string()).with_style(
        Style::default()
          .with(StyleDeclaration::display(Display::InlineFlex))
          .with(StyleDeclaration::background_color(ColorInput::Value(
            Color([0, 128, 0, 255]),
          ))),
      ),
    ])
    .with_style(
      Style::default()
        .with(StyleDeclaration::display(Display::InlineBlock))
        .with(StyleDeclaration::background_color(ColorInput::Value(
          Color([0, 0, 255, 128]),
        )))
        .with(StyleDeclaration::font_style(FontStyle::italic()))
        .with(StyleDeclaration::vertical_align(VerticalAlign::Keyword(
          VerticalAlignKeyword::Middle,
        )))
        .with_padding(Sides([Px(10.0); 4])),
    ),
    Node::text(" Red Underline".to_string()).with_style(
      Style::default()
        .with(StyleDeclaration::display(Display::Inline))
        .with(StyleDeclaration::color(ColorInput::Value(Color([
          255, 0, 0, 255,
        ]))))
        .with_text_decoration(
          TextDecoration::builder()
            .line(TextDecorationLines::UNDERLINE)
            .build(),
        ),
    ),
  ];

  let node = Node::container(decorated_children).with_style(
    Style::default()
      .with(StyleDeclaration::display(Display::Flex))
      .with(StyleDeclaration::display(Display::Block))
      .with(StyleDeclaration::width(Percentage(100.0)))
      .with(StyleDeclaration::height(Percentage(100.0)))
      .with(StyleDeclaration::background_color(ColorInput::Value(
        Color::white(),
      )))
      .with_padding(Sides([Px(40.0); 4]))
      .with(StyleDeclaration::font_size(Px(48.0).into())),
  );

  run_fixture_test(node, "inline_text_decorations");
}

#[test]
fn inline_social_post_regression() {
  let post = |name: &str,
              handle: &str,
              time: &str,
              content: &str,
              likes: &str,
              comments: &str,
              with_icons: bool,
              avatar: Color|
   -> Node {
    let content = if with_icons {
      format!("{content} 🚀🔥")
    } else {
      content.to_string()
    };

    Node::container([
      Node::container([
        Node::container([]).with_style(
          Style::default()
            .with(StyleDeclaration::display(Display::Flex))
            .with(StyleDeclaration::width(Px(56.0)))
            .with(StyleDeclaration::height(Px(56.0)))
            .with_border_radius(BorderRadius(Sides([SpacePair::from_single(Px(28.0)); 4])))
            .with(StyleDeclaration::background_color(ColorInput::Value(
              avatar,
            )))
            .with_margin(Sides([Px(0.0), Px(16.0), Px(0.0), Px(0.0)])),
        ),
        Node::container([
          Node::text(name.to_string()).with_style(
            Style::default()
              .with(StyleDeclaration::display(Display::Block))
              .with(StyleDeclaration::font_size(Px(20.0).into()))
              .with(StyleDeclaration::font_weight(FontWeight::from(700.0)))
              .with(StyleDeclaration::color(ColorInput::Value(Color::white()))),
          ),
          Node::text(format!("{handle} · {time}")).with_style(
            Style::default()
              .with(StyleDeclaration::display(Display::Block))
              .with(StyleDeclaration::font_size(Px(18.0).into()))
              .with(StyleDeclaration::color(ColorInput::Value(Color([
                136, 153, 166, 255,
              ])))),
          ),
        ])
        .with_style(
          Style::default()
            .with(StyleDeclaration::display(Display::Flex))
            .with(StyleDeclaration::display(Display::Flex))
            .with(StyleDeclaration::flex_direction(FlexDirection::Column)),
        ),
      ])
      .with_style(
        Style::default()
          .with(StyleDeclaration::display(Display::Flex))
          .with(StyleDeclaration::align_items(AlignItems::Center))
          .with_margin(Sides([Px(0.0), Px(0.0), Px(16.0), Px(0.0)])),
      ),
      Node::text(content).with_style(
        Style::default()
          .with(StyleDeclaration::display(Display::Block))
          .with(StyleDeclaration::font_size(Px(22.0).into()))
          .with(StyleDeclaration::line_height(LineHeight::Length(Em(1.5))))
          .with(StyleDeclaration::color(ColorInput::Value(Color::white())))
          .with_margin(Sides([Px(0.0), Px(0.0), Px(20.0), Px(0.0)]))
          .with_white_space(WhiteSpace::pre_wrap()),
      ),
      Node::container([
        Node::text(format!("💬 {comments}")).with_style(
          Style::default()
            .with(StyleDeclaration::display(Display::Inline))
            .with(StyleDeclaration::font_size(Px(18.0).into())),
        ),
        Node::text(format!(" 🔁 {}", likes.parse::<u32>().unwrap_or(0) / 4)).with_style(
          Style::default()
            .with(StyleDeclaration::display(Display::Inline))
            .with(StyleDeclaration::font_size(Px(18.0).into())),
        ),
        Node::text(format!(" ❤️ {likes}")).with_style(
          Style::default()
            .with(StyleDeclaration::display(Display::Inline))
            .with(StyleDeclaration::font_size(Px(18.0).into())),
        ),
      ])
      .with_style(
        Style::default()
          .with(StyleDeclaration::display(Display::Flex))
          .with(StyleDeclaration::color(ColorInput::Value(Color([
            136, 153, 166, 255,
          ]))))
          .with_gap(SpacePair::from_single(Px(24.0).into())),
      ),
    ])
    .with_style(
      Style::default()
        .with(StyleDeclaration::display(Display::Flex))
        .with(StyleDeclaration::flex_direction(FlexDirection::Column))
        .with(StyleDeclaration::background_color(ColorInput::Value(
          Color([25, 39, 52, 255]),
        )))
        .with_border_radius(BorderRadius(Sides([SpacePair::from_single(Px(16.0)); 4])))
        .with_padding(Sides([Px(24.0); 4]))
        .with_border_width(Sides([Px(1.0).into(); 4]))
        .with_border_style(Sides([BorderStyle::Solid; 4]))
        .with_border_color(Sides([ColorInput::Value(Color([56, 68, 77, 255])); 4])),
    )
  };

  let node = Node::container([Node::container([
    post(
      "Sarah Jenkins",
      "@sjenkins",
      "2h",
      "Just deployed our new rendering pipeline! The performance gains are absolutely incredible. Seeing a 40% reduction in TTFB across all endpoints.",
      "1200",
      "34",
      true,
      Color([56, 141, 229, 255]),
    ),
    post(
      "Mike Chen",
      "@mike_codes",
      "4h",
      "Is anyone else obsessed with how clean the Satori APIs are? Moving our open graph image generation to Edge has been a game changer for our latency.",
      "856",
      "12",
      false,
      Color([111, 66, 193, 255]),
    ),
    post(
      "Design Daily",
      "@designdaily",
      "7h",
      "Remember to check your contrast ratios! Accessibility isn't an afterthought, it's a fundamental part of good software design.",
      "4500",
      "128",
      false,
      Color([0, 172, 193, 255]),
    ),
  ])
  .with_style(
    Style::default()
      .with(StyleDeclaration::display(Display::Flex))
      .with(StyleDeclaration::flex_direction(FlexDirection::Column))
      .with_gap(SpacePair::from_single(Px(24.0).into()))
      .with(StyleDeclaration::flex_grow(Some(FlexGrow(1.0)))),
  )])
  .with_style(
    Style::default()
      .with(StyleDeclaration::display(Display::Flex))
      .with(StyleDeclaration::flex_direction(FlexDirection::Column))
      .with(StyleDeclaration::width(Percentage(100.0)))
      .with(StyleDeclaration::height(Percentage(100.0)))
      .with(StyleDeclaration::background_color(ColorInput::Value(Color([
        21, 32, 43, 255,
      ]))))
      .with_padding(Sides([Px(40.0); 4]))
      .with(StyleDeclaration::font_size(Px(22.0).into()))
      .with(StyleDeclaration::line_height(LineHeight::Length(Em(1.5)))),
  );

  run_fixture_test(node, "inline_social_post_regression");
}
