use crate::ollama::OllamaModel;
use tauri::Emitter;

const OLLAMA_BASE: &str = "http://localhost:11434";

pub async fn list_models() -> anyhow::Result<Vec<OllamaModel>> {
    let resp: serde_json::Value = reqwest::Client::new()
        .get(format!("{OLLAMA_BASE}/api/tags"))
        .send()
        .await?
        .json()
        .await?;

    let models = resp["models"]
        .as_array()
        .map(|arr| {
            arr.iter()
                .filter_map(|m| {
                    Some(OllamaModel {
                        name: m["name"].as_str()?.to_string(),
                        size: m["size"].as_u64().unwrap_or(0),
                        modified: m["modified_at"].as_str().unwrap_or("").to_string(),
                    })
                })
                .collect()
        })
        .unwrap_or_default();

    Ok(models)
}

pub async fn pull_model(app_handle: tauri::AppHandle, model_name: &str) -> anyhow::Result<()> {
    let client = reqwest::Client::new();
    let mut resp = client
        .post(format!("{OLLAMA_BASE}/api/pull"))
        .json(&serde_json::json!({ "name": model_name, "stream": true }))
        .send()
        .await?;

    while let Some(chunk) = resp.chunk().await? {
        if let Ok(s) = String::from_utf8(chunk.to_vec()) {
            for line in s.lines() {
                if let Ok(json) = serde_json::from_str::<serde_json::Value>(line) {
                    let status = json["status"].as_str().unwrap_or("").to_string();
                    let total = json["total"].as_u64().unwrap_or(0);
                    let completed = json["completed"].as_u64().unwrap_or(0);
                    let percent = if total > 0 {
                        (completed as f64 / total as f64 * 100.0) as u32
                    } else {
                        0
                    };

                    let _ = app_handle.emit(
                        "model://progress",
                        serde_json::json!({
                            "name": model_name,
                            "status": status,
                            "total": total,
                            "completed": completed,
                            "progress": percent,
                        }),
                    );
                }
            }
        }
    }
    Ok(())
}

pub async fn delete_model(model_name: &str) -> anyhow::Result<()> {
    let resp = reqwest::Client::new()
        .delete(format!("{OLLAMA_BASE}/api/delete"))
        .json(&serde_json::json!({ "name": model_name }))
        .send()
        .await?;

    if !resp.status().is_success() {
        anyhow::bail!("Failed to delete model: {}", resp.status());
    }
    Ok(())
}
