use crate::message::Message;

use rust_i18n::t;
use std::io::Write;
use std::os::unix::net::UnixStream;
use std::process::Command;

#[derive( Debug, Clone, Copy, PartialEq, Eq )]
pub enum PowerAction
{
	Lock,
	Suspend,
	Logout,
	Reboot,
	PowerOff,
	Cancel,
}

pub struct PowerMenu
{
	pub visible: bool,
}

impl PowerMenu
{
	pub fn new() -> Self
	{
		Self { visible: false }
	}

	pub fn show( &mut self )
	{
		self.visible = true;
	}

	pub fn dismiss( &mut self )
	{
		self.visible = false;
	}

	/// Try the loginmanager daemon first (runs as root, no polkit required);
	/// fall back to busctl → logind when the daemon socket is unreachable.
	fn daemon_power_call( method: &str )
	{
		let sock_path = std::env::var( "LOGINMANAGER_SOCK" )
			.unwrap_or_else( |_| "/run/loginmanager/ctrl.sock".to_string() );

		if let Ok( mut stream ) = UnixStream::connect( &sock_path )
		{
			let body = format!( r#"{{"type":"{}"}}"#, method );
			let len  = ( body.len() as u32 ).to_le_bytes();
			let _ = stream.write_all( &len );
			let _ = stream.write_all( body.as_bytes() );
			let _ = stream.flush();
			return;
		}
		// Fallback: call logind directly with interactive=false.  This works
		// when the session is recognised as "active" by polkit.
		if let Err( e ) = Command::new( "busctl" )
			.args( [
				"call", "--system",
				"org.freedesktop.login1",
				"/org/freedesktop/login1",
				"org.freedesktop.login1.Manager",
				method,
				"b", "false",
			] )
			.spawn()
		{
			tracing::error!( "Failed to invoke logind {method}: {e}" );
		}
	}

	pub fn execute( action: PowerAction )
	{
		let method = match action
		{
			PowerAction::PowerOff => "PowerOff",
			PowerAction::Reboot   => "Reboot",
			PowerAction::Suspend  => "Suspend",
			PowerAction::Lock | PowerAction::Logout | PowerAction::Cancel => return,
		};
		Self::daemon_power_call( method );
	}

	pub fn view( &self ) -> ltk::Element<Message>
	{
		let panel = ltk::column::<Message>()
			.padding( 20.0 )
			.spacing( 12.0 )
			.max_width( 300.0 )
			.push(
				ltk::text( t!( "powermenu_title" ).to_string() )
					.size( 18.0 )
					.color( ltk::theme_palette().text_primary )
					.align_center(),
			)
			.push(
				ltk::button::<Message>( t!( "power_lock_screen" ).to_string() )
					.on_press( Message::PowerAction( PowerAction::Lock ) ),
			)
			.push(
				ltk::button::<Message>( t!( "power_suspend" ).to_string() )
					.on_press( Message::PowerAction( PowerAction::Suspend ) ),
			)
			.push(
				ltk::button::<Message>( t!( "power_log_out" ).to_string() )
					.variant( ltk::ButtonVariant::Secondary )
					.on_press( Message::PowerAction( PowerAction::Logout ) ),
			)
			.push(
				ltk::button::<Message>( t!( "power_restart" ).to_string() )
					.on_press( Message::PowerAction( PowerAction::Reboot ) ),
			)
			.push(
				ltk::button::<Message>( t!( "power_off" ).to_string() )
					.on_press( Message::PowerAction( PowerAction::PowerOff ) ),
			)
			.push(
				ltk::button::<Message>( t!( "power_cancel" ).to_string() )
					.variant( ltk::ButtonVariant::Tertiary )
					.on_press( Message::PowerAction( PowerAction::Cancel ) ),
			);

		ltk::column::<Message>()
			.padding( 0.0 )
			.spacing( 0.0 )
			.push( ltk::spacer() )
			.push( panel )
			.push( ltk::spacer() )
			.into()
	}
}
