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

use super::*;

#[ test ]
fn text_button_focusable_by_default()
{
	let b = Button::<()>::new( "ok".into() );
	assert!( b.focusable );
}

#[ test ]
fn icon_button_focusable_by_default()
{
	let b = Button::<()>::new_icon( Arc::new( vec![] ), 0, 0 );
	assert!( b.focusable );
}

#[ test ]
fn focusable_builder_disables_focus()
{
	let b = Button::<()>::new( "ok".into() ).focusable( false );
	assert!( !b.focusable );
}

#[ test ]
fn focusable_builder_re_enables_focus()
{
	let b = Button::<()>::new( "ok".into() ).focusable( false ).focusable( true );
	assert!( b.focusable );
}

#[ test ]
fn on_press_none_by_default()
{
	let b = Button::<()>::new( "ok".into() );
	assert!( b.on_press.is_none() );
}

#[ test ]
fn tooltip_none_by_default()
{
	let b = Button::<()>::new( "ok".into() );
	assert!( b.tooltip.is_none() );
	let b = Button::<()>::new_icon( Arc::new( vec![] ), 0, 0 );
	assert!( b.tooltip.is_none() );
}

#[ test ]
fn tooltip_builder_sets_text()
{
	let b = Button::<()>::new( "ok".into() ).tooltip( "Save document" );
	assert_eq!( b.tooltip.as_deref(), Some( "Save document" ) );
}

#[ test ]
fn tooltip_survives_map_msg()
{
	let b = Button::<()>::new( "ok".into() ).tooltip( "Hint" );
	let f: super::super::MapFn<(), u32> = std::sync::Arc::new( |()| 0u32 );
	let mapped = b.map_msg( &f );
	assert_eq!( mapped.tooltip.as_deref(), Some( "Hint" ) );
}

#[ test ]
fn element_tooltip_returns_button_tooltip()
{
	let e: super::super::Element<()> = Button::<()>::new( "ok".into() ).tooltip( "Hi" ).into_element();
	assert_eq!( e.tooltip(), Some( "Hi" ) );
}

#[ test ]
fn element_tooltip_none_for_non_button_widgets()
{
	let t: super::super::Element<()> = super::super::text( "label" ).into();
	assert!( t.tooltip().is_none() );
}

#[ test ]
fn on_press_maybe_none_leaves_disabled()
{
	let b = Button::<()>::new( "ok".into() ).on_press_maybe( None );
	assert!( b.on_press.is_none() );
}

#[ test ]
fn repeating_off_by_default()
{
	let b = Button::<()>::new( "ok".into() );
	assert!( !b.repeating );
}

#[ test ]
fn repeating_builder_sets_flag()
{
	let b = Button::<()>::new( "ok".into() ).repeating( true );
	assert!( b.repeating );
	let b = b.repeating( false );
	assert!( !b.repeating );
}

#[ test ]
fn font_size_none_by_default_follows_widget_scaling()
{
	let _g = crate::TEST_GLOBALS_LOCK.lock().unwrap_or_else( |e| e.into_inner() );
	let b      = Button::<()>::new( "ok".into() );
	let canvas = Canvas::new( 400, 800 );
	assert!( b.font_size.is_none() );
	// The default routes through the widget-scaling mode, not a raw constant.
	assert_eq!( b.label_font_size( &canvas ), canvas.font_px( theme::FONT_SIZE ) );
}

#[ test ]
fn font_size_builder_resolves_length_against_viewport()
{
	// vmin on a 400×800 surface → 10 % of the smaller side (400) = 40 px.
	let b      = Button::<()>::new( "ok".into() ).font_size( Length::vmin( 10.0 ) );
	let canvas = Canvas::new( 400, 800 );
	assert_eq!( b.label_font_size( &canvas ), 40.0 );
}

#[ test ]
fn font_size_survives_map_msg()
{
	let f: super::super::MapFn<i32, ()> = std::sync::Arc::new( |_| () );
	let b: Button<()> = Button::<i32>::new( "ok".into() )
		.font_size( Length::px( 21.0 ) )
		.map_msg( &f );
	assert_eq!( b.font_size, Some( Length::px( 21.0 ) ) );
}

#[ test ]
fn height_none_by_default_follows_widget_scaling()
{
	let _g = crate::TEST_GLOBALS_LOCK.lock().unwrap_or_else( |e| e.into_inner() );
	let b      = Button::<()>::new( "ok".into() );
	let canvas = Canvas::new( 400, 800 );
	assert!( b.height.is_none() );
	// The default routes through the widget-scaling mode, not a raw constant.
	assert_eq!( b.preferred_size( 1000.0, &canvas ).1, canvas.geom_px( theme::HEIGHT ) );
}

#[ test ]
fn height_builder_scales_button_box_with_surface()
{
	// vmin height on a 400×800 surface → 10 % of the smaller side (400) = 40 px,
	// resolved in physical layout space (not divided by dpi_scale).
	let b      = Button::<()>::new( "ok".into() ).height( Length::vmin( 10.0 ) );
	let canvas = Canvas::new( 400, 800 );
	assert_eq!( b.preferred_size( 1000.0, &canvas ).1, 40.0 );
}

#[ test ]
fn width_none_by_default_sizes_to_content()
{
	let _g = crate::TEST_GLOBALS_LOCK.lock().unwrap_or_else( |e| e.into_inner() );
	let b      = Button::<()>::new( "ok".into() );
	let canvas = Canvas::new( 400, 800 );
	assert!( b.width.is_none() );
	// No pinned width → sizes to the label + padding, narrower than a
	// generous max_width.
	assert!( b.preferred_size( 1000.0, &canvas ).0 < 1000.0 );
}

#[ test ]
fn width_builder_pins_button_width()
{
	// vmin width on a 400×800 surface → 10 % of the smaller side (400) = 40 px,
	// resolved in physical layout space, clamped to the available max_width.
	let b      = Button::<()>::new( "ok".into() ).width( Length::vmin( 10.0 ) );
	let canvas = Canvas::new( 400, 800 );
	assert_eq!( b.preferred_size( 1000.0, &canvas ).0, 40.0 );
}
