use super::AudioState;
use super::throttled_cmd;
use std::process::Command;
use std::sync::LazyLock;
use std::sync::Mutex;
use std::sync::mpsc::Sender;

pub fn get_audio_state() -> AudioState
{
	// Try PipeWire (wpctl)
	if let Ok( out ) = Command::new( "wpctl" )
		.args( ["get-volume", "@DEFAULT_AUDIO_SINK@"] )
		.output()
	{
		if out.status.success()
		{
			let stdout = String::from_utf8_lossy( &out.stdout );
			let muted = stdout.contains( "[MUTED]" );
			if let Some( vol_str ) = stdout.split_whitespace().nth( 1 )
			{
				if let Ok( vol ) = vol_str.parse::<f32>()
				{
					return AudioState {
						volume: ( vol * 100.0 ) as u8,
						muted,
					};
				}
			}
		}
	}

	// Fallback to PulseAudio (pactl)
	if let Ok( out ) = Command::new( "pactl" )
		.args( ["get-sink-volume", "@DEFAULT_SINK@"] )
		.output()
	{
		if out.status.success()
		{
			let stdout = String::from_utf8_lossy( &out.stdout );
			for part in stdout.split_whitespace()
			{
				if part.ends_with( '%' )
				{
					if let Ok( vol ) = part.trim_end_matches( '%' ).parse::<u8>()
					{
						let muted = Command::new( "pactl" )
							.args( ["get-sink-mute", "@DEFAULT_SINK@"] )
							.output()
							.map( |o| String::from_utf8_lossy( &o.stdout ).contains( "yes" ) )
							.unwrap_or( false );
						return AudioState { volume: vol, muted };
					}
				}
			}
		}
	}

	AudioState::default()
}

/// Hot path for slider drags / hardware key presses. Pushes the new
/// percent onto the worker channel; the worker collapses bursts to the
/// most recent value, runs `wpctl` once and reaps it. See
/// [`super::throttled_cmd`] for the full rationale.
pub fn set_volume( vol: u8 )
{
	let _ = VOLUME_TX.lock().unwrap().send( vol );
}

pub fn set_muted( muted: bool )
{
	let _ = MUTE_TX.lock().unwrap().send( muted );
}

static VOLUME_TX: LazyLock<Mutex<Sender<u8>>> = LazyLock::new( ||
{
	Mutex::new( throttled_cmd::spawn_worker( | vol: u8 |
	{
		let val = format!( "{:.2}", vol as f32 / 100.0 );
		match Command::new( "wpctl" )
			.args( ["set-volume", "@DEFAULT_AUDIO_SINK@", &val] )
			.spawn()
		{
			Ok( mut child ) => { let _ = child.wait(); }
			Err( e )        => tracing::error!( "Failed to set volume: {}", e ),
		}
	} ) )
} );

static MUTE_TX: LazyLock<Mutex<Sender<bool>>> = LazyLock::new( ||
{
	Mutex::new( throttled_cmd::spawn_worker( | muted: bool |
	{
		let val = if muted { "1" } else { "0" };
		match Command::new( "wpctl" )
			.args( ["set-mute", "@DEFAULT_AUDIO_SINK@", val] )
			.spawn()
		{
			Ok( mut child ) => { let _ = child.wait(); }
			Err( e )        => tracing::error!( "Failed to set mute: {}", e ),
		}
	} ) )
} );
