// filepath: src-tauri/src/commands.rs
use tauri::{AppHandle, Manager};
use crate::{binary_manager, downloader, storage};
use crate::downloader::DownloadOptions;
use crate::storage::{Settings, HistoryItem};
use uuid::Uuid;
use std::path::Path;

#[tauri::command]
pub async fn init_ytdlp(app: AppHandle) -> Result<bool, String> {
    if binary_manager::check_binaries(&app) {
        return Ok(true);
    }
    
    // If not found, try to download
    match binary_manager::ensure_binaries(&app).await {
        Ok(_) => Ok(true),
        Err(e) => Err(format!("Failed to download binaries: {}", e)),
    }
}

#[tauri::command]
pub async fn update_ytdlp(app: AppHandle) -> Result<String, String> {
    binary_manager::update_ytdlp(&app).await.map_err(|e| e.to_string())
}

#[tauri::command]
pub async fn update_quickjs(app: AppHandle) -> Result<String, String> {
    binary_manager::update_qjs(&app).await.map_err(|e| e.to_string())
}

#[tauri::command]
pub async fn update_ffmpeg(app: AppHandle) -> Result<String, String> {
    binary_manager::update_ffmpeg(&app).await.map_err(|e| e.to_string())
}

#[tauri::command]
pub fn get_ytdlp_version(app: AppHandle) -> Result<String, String> {
    binary_manager::get_ytdlp_version(&app).map_err(|e| e.to_string())
}

#[tauri::command]
pub fn get_quickjs_version(app: AppHandle) -> Result<String, String> {
    binary_manager::get_qjs_version(&app).map_err(|e| e.to_string())
}

#[tauri::command]
pub fn get_ffmpeg_version(app: AppHandle) -> Result<String, String> {
    binary_manager::get_ffmpeg_version(&app).map_err(|e| e.to_string())
}

#[tauri::command]
pub async fn fetch_image(url: String) -> Result<String, String> {
    use base64::{Engine as _, engine::general_purpose};

    let client = reqwest::Client::new();
    let res = client.get(&url)
        .header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36")
        .send()
        .await
        .map_err(|e| e.to_string())?;

    let bytes = res.bytes().await.map_err(|e| e.to_string())?;
    
    // Convert to base64
    let b64 = general_purpose::STANDARD.encode(&bytes);
    
    // Simple heuristic for mime type
    let mime = if url.to_lowercase().ends_with(".png") { "image/png" } else { "image/jpeg" };
    
    Ok(format!("data:{};base64,{}", mime, b64))
}

#[tauri::command]
pub async fn fetch_metadata(app: AppHandle, url: String, parse_mix_playlist: bool) -> Result<downloader::MetadataResult, String> {
    downloader::fetch_metadata(&app, &url, parse_mix_playlist).await.map_err(|e| e.to_string())
}

#[tauri::command]
pub async fn start_download(app: AppHandle, url: String, options: DownloadOptions, metadata: downloader::VideoMetadata) -> Result<String, String> {
    // Generate a task ID
    let id = Uuid::new_v4().to_string();
    let id_clone = id.clone();
    
    // Spawn the download task
    tauri::async_runtime::spawn(async move {
        let res = downloader::download_video(app.clone(), id_clone.clone(), url.clone(), options.clone()).await;
        
        let status = if res.is_ok() { "success" } else { "failed" };
        
        // Add to history
        let output_dir = options.output_path.clone(); // Store the directory user selected
        
        let item = HistoryItem {
            id: id_clone,
            title: metadata.title,
            thumbnail: metadata.thumbnail,
            url: url,
            output_path: output_dir, 
            timestamp: chrono::Utc::now(),
            status: status.to_string(),
            format: options.output_format,
        };
        
        let _ = storage::add_history_item(&app, item);
    });

    Ok(id)
}

#[tauri::command]
pub fn get_settings(app: AppHandle) -> Result<Settings, String> {
    storage::load_settings(&app).map_err(|e| e.to_string())
}

#[tauri::command]
pub fn save_settings(app: AppHandle, settings: Settings) -> Result<(), String> {
    storage::save_settings(&app, &settings).map_err(|e| e.to_string())
}

#[tauri::command]
pub fn get_history(app: AppHandle) -> Result<Vec<HistoryItem>, String> {
    storage::load_history(&app).map_err(|e| e.to_string())
}

#[tauri::command]
pub fn clear_history(app: AppHandle) -> Result<(), String> {
    storage::clear_history(&app).map_err(|e| e.to_string())
}

#[tauri::command]
pub fn delete_history_item(app: AppHandle, id: String) -> Result<(), String> {
    storage::delete_history_item(&app, &id).map_err(|e| e.to_string())
}

#[tauri::command]
pub async fn close_splash(app: AppHandle) {
    if let Some(splash) = app.get_webview_window("splashscreen") {
        splash.close().unwrap();
    }
    if let Some(main) = app.get_webview_window("main") {
        main.show().unwrap();
    }
}

#[tauri::command]
pub fn open_in_explorer(app: AppHandle, path: String) -> Result<(), String> {
    let path_to_open = if Path::new(&path).exists() {
        path
    } else {
        app.path().download_dir()
            .map(|p| p.to_string_lossy().to_string())
            .unwrap_or_else(|_| ".".to_string())
    };

    #[cfg(target_os = "windows")]
    {
        std::process::Command::new("explorer")
            .arg(path_to_open)
            .spawn()
            .map_err(|e| e.to_string())?;
    }
    #[cfg(target_os = "macos")]
    {
        std::process::Command::new("open")
            .arg(path_to_open)
            .spawn()
            .map_err(|e| e.to_string())?;
    }
    Ok(())
}