use super::db::{ensure_library_schema, list_games, update_customization};
use super::models::{GameCustomizationRequest, LibraryGame, LibraryScanRequest, ScanSummary};
use super::{list_visible_games, scan_library};
use crate::storage::AppStorage;
use serde::Serialize;
use std::path::PathBuf;

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct LaunchLibraryGameResult {
    pub launched: bool,
    pub action: String,
    pub message: String,
}

#[tauri::command]
pub async fn scan_library_command(
    request: LibraryScanRequest,
    storage: tauri::State<'_, AppStorage>,
) -> Result<ScanSummary, String> {
    let storage = storage.inner().clone();
    let local_folders = request
        .local_folders
        .into_iter()
        .map(PathBuf::from)
        .collect::<Vec<_>>();

    tauri::async_runtime::spawn_blocking(move || scan_library(storage, local_folders))
        .await
        .map_err(|err| format!("Library scanner task failed: {err}"))?
}

#[tauri::command]
pub async fn list_library_games(
    storage: tauri::State<'_, AppStorage>,
) -> Result<Vec<LibraryGame>, String> {
    let storage = storage.inner().clone();
    tauri::async_runtime::spawn_blocking(move || list_visible_games(&storage))
        .await
        .map_err(|err| format!("Library list task failed: {err}"))?
}

#[tauri::command]
pub async fn update_library_game(
    request: GameCustomizationRequest,
    storage: tauri::State<'_, AppStorage>,
) -> Result<Option<LibraryGame>, String> {
    let storage = storage.inner().clone();
    tauri::async_runtime::spawn_blocking(move || {
        let conn = storage.connect_library()?;
        ensure_library_schema(&conn)?;
        update_customization(&conn, request)
    })
    .await
    .map_err(|err| format!("Library update task failed: {err}"))?
}

#[tauri::command]
pub async fn launch_library_game(
    game_id: i64,
    storage: tauri::State<'_, AppStorage>,
) -> Result<LaunchLibraryGameResult, String> {
    let storage = storage.inner().clone();
    tauri::async_runtime::spawn_blocking(move || {
        let conn = storage.connect_library()?;
        ensure_library_schema(&conn)?;
        let game = list_games(&conn, true)?
            .into_iter()
            .find(|game| game.id == game_id)
            .ok_or_else(|| "Library app was not found.".to_string())?;

        let launch_target = game
            .launch_command
            .as_deref()
            .or(game.executable_path.as_deref())
            .unwrap_or(game.install_path.as_str());

        // Future provider launchers plug in here:
        // Steam: steam://run/<appid>, GOG/Epic URI handlers, emulator profiles,
        // and native executable spawning with per-app environment overrides.
        println!(
            "[NebulaOS] launch placeholder: {} via {}",
            game.user_title.as_deref().unwrap_or(&game.title),
            launch_target
        );

        Ok(LaunchLibraryGameResult {
            launched: true,
            action: "placeholder".to_string(),
            message: format!(
                "Launch requested for {}.",
                game.user_title.unwrap_or(game.title)
            ),
        })
    })
    .await
    .map_err(|err| format!("Library launch task failed: {err}"))?
}
