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 {
        "tz" | "timezone" => tz(session, &parts[1..], mode).await,
        "locale" => locale(session, &parts[1..], mode).await,
        "media" => media(session, &parts[1..], mode).await,
        "geo" => geo(session, &parts[1..], mode).await,
        other => output_err(
            mode,
            &format!("Unknown emulate subcommand: {other}. Use 'tz', 'locale', 'media', or 'geo'"),
        ),
    }
}

async fn tz(session: &BrowserSession, parts: &[&str], mode: OutputMode) {
    let timezone = parts.first().copied().unwrap_or("").trim();
    if timezone.is_empty() {
        output_err(mode, "Usage: emulate tz <timezone-id>");
        return;
    }
    match session.emulate_timezone(timezone).await {
        Ok(msg) => output_ok(
            mode,
            &msg,
            json!({"action": "emulate_tz", "timezone": timezone}),
        ),
        Err(e) => output_err(mode, &e.to_string()),
    }
}

async fn locale(session: &BrowserSession, parts: &[&str], mode: OutputMode) {
    let loc = parts.first().copied().unwrap_or("").trim();
    if loc.is_empty() {
        output_err(mode, "Usage: emulate locale <locale>");
        return;
    }
    match session.emulate_locale(loc).await {
        Ok(msg) => output_ok(
            mode,
            &msg,
            json!({"action": "emulate_locale", "locale": loc}),
        ),
        Err(e) => output_err(mode, &e.to_string()),
    }
}

async fn media(session: &BrowserSession, parts: &[&str], mode: OutputMode) {
    if parts.len() < 2 {
        output_err(mode, "Usage: emulate media <feature> <value>");
        return;
    }
    let feature = parts[0];
    let value = parts[1..].join(" ");
    match session.emulate_media_feature(feature, &value).await {
        Ok(msg) => output_ok(
            mode,
            &msg,
            json!({"action": "emulate_media", "feature": feature, "value": value}),
        ),
        Err(e) => output_err(mode, &e.to_string()),
    }
}

async fn geo(session: &BrowserSession, parts: &[&str], mode: OutputMode) {
    if parts.len() < 2 {
        output_err(mode, "Usage: emulate geo <lat> <lng>");
        return;
    }
    let lat: f64 = match parts[0].parse() {
        Ok(v) => v,
        Err(_) => {
            output_err(mode, "lat must be a number");
            return;
        }
    };
    let lng: f64 = match parts[1].parse() {
        Ok(v) => v,
        Err(_) => {
            output_err(mode, "lng must be a number");
            return;
        }
    };
    match session.set_geolocation(lat, lng).await {
        Ok(msg) => output_ok(
            mode,
            &msg,
            json!({"action": "emulate_geo", "lat": lat, "lng": lng}),
        ),
        Err(e) => output_err(mode, &e.to_string()),
    }
}
