use std::time::Duration;

use night_fury_core::BrowserSession;
use serde_json::json;

use crate::output::{output_err, output_ok, OutputMode};

pub async fn dispatch(session: &BrowserSession, parts: &[&str], mode: OutputMode) {
    let sub = parts.first().copied().unwrap_or("");
    match sub {
        "path" => path(session, &parts[1..], mode).await,
        "wait" => wait(session, &parts[1..], mode).await,
        other => output_err(
            mode,
            &format!(
                "Unknown download subcommand: {other}. Use 'path <dir>' or 'wait [timeout_s]'"
            ),
        ),
    }
}

async fn path(session: &BrowserSession, parts: &[&str], mode: OutputMode) {
    let dir = parts.first().copied().unwrap_or("").trim();
    if dir.is_empty() {
        output_err(mode, "Usage: download path <dir>");
        return;
    }
    match session.set_download_path(dir).await {
        Ok(()) => output_ok(
            mode,
            &format!("Download path set to {dir}"),
            json!({"action": "download_path", "path": dir}),
        ),
        Err(e) => output_err(mode, &e.to_string()),
    }
}

async fn wait(session: &BrowserSession, parts: &[&str], mode: OutputMode) {
    let timeout_s: u64 = parts.first().and_then(|s| s.parse().ok()).unwrap_or(30);
    match session
        .wait_for_download(Duration::from_secs(timeout_s))
        .await
    {
        Ok(info) => {
            let human = format!("Downloaded: {} -> {}", info.filename, info.path);
            output_ok(
                mode,
                &human,
                json!({
                    "action": "download_complete",
                    "path": info.path,
                    "filename": info.filename,
                    "url": info.url,
                    "size": info.size,
                }),
            );
        }
        Err(e) => output_err(mode, &e.to_string()),
    }
}
