//! Remote Jellyfin session control commands (casting to another device).
//!
//! TRACES: UR-010, UR-046 | IR-012, IR-028, JA-022, JA-023, JA-025, JA-026 | DR-037, DR-058
//!
//! These thin command adapters forward control actions to the active Jellyfin
//! session via the player's configured `JellyfinClient`.

use tauri::State;

use super::PlayerStateWrapper;
use crate::jellyfin::client::LmsSyncGroup;

/// Play items on a remote Jellyfin session (casting)
#[tauri::command]
#[specta::specta]
pub async fn remote_play_on_session(
    player: State<'_, PlayerStateWrapper>,
    session_id: String,
    item_ids: Vec<String>,
    start_index: usize,
) -> Result<(), String> {
    log::info!(
        "[RemoteSession] Playing {} items on session {} (start index: {})",
        item_ids.len(),
        session_id,
        start_index
    );
    log::info!("[RemoteSession] Item IDs: {:?}", item_ids);

    let client_opt = {
        let controller = player.0.lock().await;
        controller
            .jellyfin_client()
            .lock()
            .map_err(|e| e.to_string())?
            .clone()
    };

    if let Some(client) = client_opt {
        log::info!("[RemoteSession] Jellyfin client IS configured, calling play_on_session");
        client
            .play_on_session(session_id, item_ids, start_index, None)
            .await?;
        log::info!("[RemoteSession] Successfully started playback on remote session");
        Ok(())
    } else {
        log::error!("[RemoteSession] Jellyfin client is NOT configured! User needs to log out/in or restart app");
        Err(
            "Jellyfin client not configured - please restart the app or log out and log back in"
                .to_string(),
        )
    }
}

/// Send a playback command to a remote session
#[tauri::command]
#[specta::specta]
pub async fn remote_send_command(
    player: State<'_, PlayerStateWrapper>,
    session_id: String,
    command: String,
) -> Result<(), String> {
    log::info!(
        "[RemoteSession] Sending command '{}' to session {}",
        command,
        session_id
    );

    let client_opt = {
        let controller = player.0.lock().await;
        controller
            .jellyfin_client()
            .lock()
            .map_err(|e| e.to_string())?
            .clone()
    };

    if let Some(client) = client_opt {
        client.send_session_command(session_id, &command).await?;
        log::info!("[RemoteSession] Command sent successfully");
        Ok(())
    } else {
        Err("Jellyfin client not configured".to_string())
    }
}

/// Seek on a remote session
#[tauri::command]
#[specta::specta]
pub async fn remote_session_seek(
    player: State<'_, PlayerStateWrapper>,
    session_id: String,
    position_ticks: i64,
) -> Result<(), String> {
    log::info!(
        "[RemoteSession] Seeking to {} ticks on session {}",
        position_ticks,
        session_id
    );

    let client_opt = {
        let controller = player.0.lock().await;
        controller
            .jellyfin_client()
            .lock()
            .map_err(|e| e.to_string())?
            .clone()
    };

    if let Some(client) = client_opt {
        client.session_seek(session_id, position_ticks).await?;
        log::info!("[RemoteSession] Seek successful");
        Ok(())
    } else {
        Err("Jellyfin client not configured".to_string())
    }
}

/// Set volume on a remote session
#[tauri::command]
#[specta::specta]
pub async fn remote_session_set_volume(
    player: State<'_, PlayerStateWrapper>,
    session_id: String,
    volume: i32,
) -> Result<(), String> {
    log::info!(
        "[RemoteSession] Setting volume to {} on session {}",
        volume,
        session_id
    );

    let client_opt = {
        let controller = player.0.lock().await;
        controller
            .jellyfin_client()
            .lock()
            .map_err(|e| e.to_string())?
            .clone()
    };

    if let Some(client) = client_opt {
        client.session_set_volume(session_id, volume).await?;
        log::info!("[RemoteSession] Volume set successfully");
        Ok(())
    } else {
        Err("Jellyfin client not configured".to_string())
    }
}

/// Toggle mute on a remote session
#[tauri::command]
#[specta::specta]
pub async fn remote_session_toggle_mute(
    player: State<'_, PlayerStateWrapper>,
    session_id: String,
) -> Result<(), String> {
    log::info!("[RemoteSession] Toggling mute on session {}", session_id);

    let client_opt = {
        let controller = player.0.lock().await;
        controller
            .jellyfin_client()
            .lock()
            .map_err(|e| e.to_string())?
            .clone()
    };

    if let Some(client) = client_opt {
        client.session_toggle_mute(session_id).await?;
        log::info!("[RemoteSession] Mute toggled successfully");
        Ok(())
    } else {
        Err("Jellyfin client not configured".to_string())
    }
}

// --- JellyLMS multi-room sync groups (fuse / unfuse LMS zones) --------------
//
// The frontend addresses LMS players by MAC address, which it derives from a
// session's device id (`lms-{mac}`). These commands forward to the JellyLMS
// plugin REST API via the configured JellyfinClient.

/// List current LMS sync groups.
#[tauri::command]
#[specta::specta]
pub async fn lms_get_sync_groups(
    player: State<'_, PlayerStateWrapper>,
) -> Result<Vec<LmsSyncGroup>, String> {
    let client_opt = {
        let controller = player.0.lock().await;
        controller
            .jellyfin_client()
            .lock()
            .map_err(|e| e.to_string())?
            .clone()
    };

    if let Some(client) = client_opt {
        client.lms_get_sync_groups().await
    } else {
        Err("Jellyfin client not configured".to_string())
    }
}

/// Fuse LMS zones into a sync group. `master_mac` keeps playing and the
/// `slave_macs` zones join it in sync.
#[tauri::command]
#[specta::specta]
pub async fn lms_create_sync_group(
    player: State<'_, PlayerStateWrapper>,
    master_mac: String,
    slave_macs: Vec<String>,
) -> Result<(), String> {
    log::info!(
        "[LmsSync] Fusing zones: master={}, slaves={:?}",
        master_mac,
        slave_macs
    );

    let client_opt = {
        let controller = player.0.lock().await;
        controller
            .jellyfin_client()
            .lock()
            .map_err(|e| e.to_string())?
            .clone()
    };

    if let Some(client) = client_opt {
        client.lms_create_sync_group(&master_mac, slave_macs).await
    } else {
        Err("Jellyfin client not configured".to_string())
    }
}

/// Remove a single LMS zone from its sync group (decouple one player).
#[tauri::command]
#[specta::specta]
pub async fn lms_unsync_player(
    player: State<'_, PlayerStateWrapper>,
    mac: String,
) -> Result<(), String> {
    log::info!("[LmsSync] Decoupling zone {}", mac);

    let client_opt = {
        let controller = player.0.lock().await;
        controller
            .jellyfin_client()
            .lock()
            .map_err(|e| e.to_string())?
            .clone()
    };

    if let Some(client) = client_opt {
        client.lms_unsync_player(&mac).await
    } else {
        Err("Jellyfin client not configured".to_string())
    }
}

/// Dissolve an entire LMS sync group, identified by its master's MAC.
#[tauri::command]
#[specta::specta]
pub async fn lms_dissolve_sync_group(
    player: State<'_, PlayerStateWrapper>,
    master_mac: String,
) -> Result<(), String> {
    log::info!("[LmsSync] Dissolving group with master {}", master_mac);

    let client_opt = {
        let controller = player.0.lock().await;
        controller
            .jellyfin_client()
            .lock()
            .map_err(|e| e.to_string())?
            .clone()
    };

    if let Some(client) = client_opt {
        client.lms_dissolve_sync_group(&master_mac).await
    } else {
        Err("Jellyfin client not configured".to_string())
    }
}
