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

use super::*;
use crate::layout::spacer::spacer;

#[ derive( Clone, Debug, PartialEq, Eq ) ]
enum Msg { Cancel, Dismiss }

#[ test ]
fn new_defaults_are_modal_with_no_content()
{
	let d = Dialog::<Msg>::new();
	assert!( d.modal );
	assert!( d.title.is_none() );
	assert!( d.subtitle.is_none() );
	assert!( d.body.is_none() );
	assert!( d.actions.is_empty() );
	assert!( d.dismiss_msg.is_none() );
	assert!( d.cancel_msg.is_none() );
	assert_eq!( d.max_width, crate::types::Length::fluid( DEFAULT_MAX_WIDTH ) );
}

#[ test ]
fn title_and_subtitle_builders_set_strings()
{
	let d = Dialog::<Msg>::new()
		.title( "Hello" )
		.subtitle( "World" );
	assert_eq!( d.title.as_deref(),    Some( "Hello" ) );
	assert_eq!( d.subtitle.as_deref(), Some( "World" ) );
}

#[ test ]
fn body_builder_replaces_existing_body()
{
	let d = Dialog::<Msg>::new()
		.body( spacer() )
		.body( spacer() );
	assert!( d.body.is_some() );
}

#[ test ]
fn action_builder_appends_in_order()
{
	let d = Dialog::<Msg>::new()
		.action( spacer() )
		.action( spacer() )
		.action( spacer() );
	assert_eq!( d.actions.len(), 3 );
}

#[ test ]
fn modal_builder_toggles_flag()
{
	assert!( !Dialog::<Msg>::new().modal( false ).modal );
	assert!(  Dialog::<Msg>::new().modal( true  ).modal );
}

#[ test ]
fn dismiss_on_scrim_builder_records_message()
{
	let d = Dialog::<Msg>::new()
		.modal( false )
		.dismiss_on_scrim( Msg::Dismiss );
	assert_eq!( d.dismiss_msg, Some( Msg::Dismiss ) );
}

#[ test ]
fn cancel_builder_records_escape_message()
{
	let d = Dialog::<Msg>::new().cancel( Msg::Cancel );
	assert_eq!( d.cancel_msg, Some( Msg::Cancel ) );
}

#[ test ]
fn max_width_builder_overrides_default()
{
	let d = Dialog::<Msg>::new().max_width( 720.0 );
	assert_eq!( d.max_width, crate::types::Length::px( 720.0 ) );
}

#[ test ]
#[ should_panic( expected = "dismiss_on_scrim is not valid when modal=true" ) ]
fn modal_with_dismiss_panics_at_lower()
{
	// Construction allows the combination; only the lowering
	// to `Element` enforces the contract — that is where the
	// invariant matters because that is where input dispatch
	// would have to honour two contradictory rules.
	let d = Dialog::<Msg>::new()
		.modal( true )
		.dismiss_on_scrim( Msg::Dismiss );
	let _: Element<Msg> = d.into();
}

#[ test ]
fn non_modal_with_dismiss_lowers_cleanly()
{
	let d = Dialog::<Msg>::new()
		.modal( false )
		.dismiss_on_scrim( Msg::Dismiss )
		.cancel( Msg::Cancel )
		.title( "Title" );
	// Lowering must not panic.
	let _: Element<Msg> = d.into();
}

#[ test ]
fn modal_with_cancel_only_lowers_cleanly()
{
	// modal=true + cancel(...) (no dismiss_on_scrim) is the
	// canonical confirm-dialog shape.
	let d = Dialog::<Msg>::new()
		.title( "Confirm" )
		.subtitle( "Are you sure?" )
		.cancel( Msg::Cancel );
	let _: Element<Msg> = d.into();
}
