use tauri::State;
use crate::AppState;
use crate::error::AppError;
use crate::remote::{self, RemoteMachineConfig, RemoteMachineInfo};
use crate::pty::PtyOptions;
use crate::sidecar::AgentQueryOptions;

#[tauri::command]
pub async fn remote_list(state: State<'_, AppState>) -> Result<Vec<RemoteMachineInfo>, AppError> {
    Ok(state.remote_manager.list_machines().await)
}

#[tauri::command]
pub async fn remote_add(state: State<'_, AppState>, config: RemoteMachineConfig) -> Result<String, AppError> {
    Ok(state.remote_manager.add_machine(config).await)
}

#[tauri::command]
pub async fn remote_remove(state: State<'_, AppState>, machine_id: String) -> Result<(), AppError> {
    state.remote_manager.remove_machine(&machine_id).await.map_err(AppError::network)
}

#[tauri::command]
#[tracing::instrument(skip(app, state))]
pub async fn remote_connect(app: tauri::AppHandle, state: State<'_, AppState>, machine_id: String) -> Result<(), AppError> {
    state.remote_manager.connect(&app, &machine_id).await.map_err(AppError::network)
}

#[tauri::command]
#[tracing::instrument(skip(state))]
pub async fn remote_disconnect(state: State<'_, AppState>, machine_id: String) -> Result<(), AppError> {
    state.remote_manager.disconnect(&machine_id).await.map_err(AppError::network)
}

#[tauri::command]
#[tracing::instrument(skip(state, options), fields(session_id = %options.session_id))]
pub async fn remote_agent_query(state: State<'_, AppState>, machine_id: String, options: AgentQueryOptions) -> Result<(), AppError> {
    state.remote_manager.agent_query(&machine_id, &options).await.map_err(AppError::network)
}

#[tauri::command]
#[tracing::instrument(skip(state))]
pub async fn remote_agent_stop(state: State<'_, AppState>, machine_id: String, session_id: String) -> Result<(), AppError> {
    state.remote_manager.agent_stop(&machine_id, &session_id).await.map_err(AppError::network)
}

#[tauri::command]
#[tracing::instrument(skip(state), fields(shell = ?options.shell))]
pub async fn remote_pty_spawn(state: State<'_, AppState>, machine_id: String, options: PtyOptions) -> Result<String, AppError> {
    state.remote_manager.pty_spawn(&machine_id, &options).await.map_err(AppError::network)
}

#[tauri::command]
pub async fn remote_pty_write(state: State<'_, AppState>, machine_id: String, id: String, data: String) -> Result<(), AppError> {
    state.remote_manager.pty_write(&machine_id, &id, &data).await.map_err(AppError::network)
}

#[tauri::command]
pub async fn remote_pty_resize(state: State<'_, AppState>, machine_id: String, id: String, cols: u16, rows: u16) -> Result<(), AppError> {
    state.remote_manager.pty_resize(&machine_id, &id, cols, rows).await.map_err(AppError::network)
}

#[tauri::command]
pub async fn remote_pty_kill(state: State<'_, AppState>, machine_id: String, id: String) -> Result<(), AppError> {
    state.remote_manager.pty_kill(&machine_id, &id).await.map_err(AppError::network)
}

// --- SPKI certificate pinning ---

#[tauri::command]
#[tracing::instrument]
pub async fn remote_probe_spki(url: String) -> Result<String, AppError> {
    remote::probe_spki_hash(&url).await.map_err(AppError::network)
}

#[tauri::command]
#[tracing::instrument(skip(state))]
pub async fn remote_add_pin(state: State<'_, AppState>, machine_id: String, pin: String) -> Result<(), AppError> {
    state.remote_manager.add_spki_pin(&machine_id, pin).await.map_err(AppError::network)
}

#[tauri::command]
#[tracing::instrument(skip(state))]
pub async fn remote_remove_pin(state: State<'_, AppState>, machine_id: String, pin: String) -> Result<(), AppError> {
    state.remote_manager.remove_spki_pin(&machine_id, &pin).await.map_err(AppError::network)
}
