// SPDX-License-Identifier: LGPL-2.1-only
// Copyright (C) 2026 Liberux Labs, S. L. <info@liberux.net>

use super::*;
use crate::render::Canvas;

fn make_canvas() -> Canvas { Canvas::new( 800, 600 ) }

#[ test ]
fn new_uses_documented_defaults()
{
	let t = Text::new( "hello" );
	assert_eq!( t.content, "hello" );
	assert_eq!( t.size,    crate::Length::px( 16.0 ) );
	assert_eq!( t.color,   Color::WHITE );
	assert_eq!( t.align,   TextAlign::Left );
}

#[ test ]
fn size_builder_overrides_default()
{
	let t = Text::new( "" ).size( 32.0 );
	assert_eq!( t.size, crate::Length::px( 32.0 ) );
}

#[ test ]
fn size_builder_accepts_length()
{
	let t = Text::new( "" ).size( crate::Length::vmin( 5.0 ) );
	assert_eq!( t.size.base, crate::LengthBase::Vmin( 5.0 ) );
}

#[ test ]
fn color_builder_overrides_default()
{
	let t = Text::new( "" ).color( Color::rgb( 1.0, 0.0, 0.0 ) );
	assert_eq!( t.color, Color::rgb( 1.0, 0.0, 0.0 ) );
}

#[ test ]
fn align_builder_can_target_each_variant()
{
	assert_eq!( Text::new( "" ).align( TextAlign::Left   ).align, TextAlign::Left   );
	assert_eq!( Text::new( "" ).align( TextAlign::Center ).align, TextAlign::Center );
	assert_eq!( Text::new( "" ).align( TextAlign::Right  ).align, TextAlign::Right  );
}

#[ test ]
fn align_center_shorthand_matches_explicit_align()
{
	let a = Text::new( "" ).align_center();
	let b = Text::new( "" ).align( TextAlign::Center );
	assert_eq!( a.align, b.align );
}

#[ test ]
fn preferred_size_returns_non_negative_dimensions()
{
	let canvas = make_canvas();
	let ( w, h ) = Text::new( "ltk" ).preferred_size( 200.0, &canvas );
	assert!( w >= 0.0 );
	assert!( h >  0.0, "non-empty text reports a positive line height" );
}

#[ test ]
fn preferred_size_caps_width_at_max_width()
{
	// A long string must not exceed the parent-supplied bound — text
	// elides at draw time, so the layout pass needs to see at most
	// `max_width`.
	let canvas = make_canvas();
	let long  = "the quick brown fox jumps over the lazy dog";
	let ( w, _ ) = Text::new( long ).size( 24.0 ).preferred_size( 64.0, &canvas );
	assert!( w <= 64.0, "preferred width must be clamped to max_width (got {w})" );
}

#[ test ]
fn preferred_size_height_scales_with_font_size()
{
	let canvas = make_canvas();
	let ( _, h_small ) = Text::new( "x" ).size( 12.0 ).preferred_size( 200.0, &canvas );
	let ( _, h_large ) = Text::new( "x" ).size( 48.0 ).preferred_size( 200.0, &canvas );
	assert!( h_large > h_small, "larger font must report taller line height" );
}

#[ test ]
fn empty_content_still_reports_a_line_height()
{
	let canvas = make_canvas();
	let ( _, h ) = Text::new( "" ).preferred_size( 200.0, &canvas );
	// Even an empty string keeps the baseline metrics so a hidden field
	// keeps its row height inside a column.
	assert!( h > 0.0 );
}

#[ test ]
fn line_height_builder_defaults_to_one_and_clamps()
{
	assert_eq!( Text::new( "" ).line_height, 1.0 );
	assert_eq!( Text::new( "" ).line_height( 1.5 ).line_height, 1.5 );
	// Floor keeps wrapped lines from overlapping even at absurd inputs.
	assert_eq!( Text::new( "" ).line_height( 0.1 ).line_height, 0.5 );
}

#[ test ]
fn line_height_multiplies_wrapped_text_height()
{
	let canvas = make_canvas();
	// Long enough to wrap onto several lines at this width.
	let long    = "the quick brown fox jumps over the lazy dog";
	let base    = Text::new( long ).size( 24.0 ).wrap( true );
	let doubled = Text::new( long ).size( 24.0 ).wrap( true ).line_height( 2.0 );
	let h_base    = base.preferred_size( 120.0, &canvas ).1;
	let h_doubled = doubled.preferred_size( 120.0, &canvas ).1;
	// Wrapping is width-driven, so both report the same line count; doubling
	// the line height therefore doubles the reported height.
	assert!( ( h_doubled - 2.0 * h_base ).abs() < 1e-3, "h_base={h_base} h_doubled={h_doubled}" );
}

#[ test ]
fn text_align_enum_implements_partial_eq()
{
	// Compile-time guard: TextAlign must keep deriving PartialEq so
	// downstream theming code can compare alignments.
	assert_eq!( TextAlign::Left, TextAlign::Left );
	assert_ne!( TextAlign::Left, TextAlign::Right );
}
