use crate::config::{get_config, PortalConfig};
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize)]
pub struct HealthResponse {
    pub status: String,
    pub version: String,
    pub uptime_ms: u64,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct DetailedHealthResponse {
    pub status: String,
    pub version: String,
    pub uptime_ms: u64,
    pub services: ServiceHealth,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct ServiceHealth {
    pub postgres: ServiceStatus,
    pub redis: ServiceStatus,
    pub qdrant: ServiceStatus,
    pub mongodb: ServiceStatus,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct ServiceStatus {
    pub status: String,
    pub latency_ms: Option<u64>,
    pub error: Option<String>,
}

#[tauri::command]
pub async fn get_health() -> Result<HealthResponse, String> {
    let config = get_config();
    let client = reqwest::Client::new();

    let response = client
        .get(&format!("{}/health", config.api_base_url))
        .timeout(std::time::Duration::from_secs(5))
        .send()
        .await
        .map_err(|e| format!("Request failed: {}", e))?;

    if !response.status().is_success() {
        return Err(format!("API error: {}", response.status()));
    }

    let result: HealthResponse = response
        .json()
        .await
        .map_err(|e| format!("Failed to parse response: {}", e))?;

    Ok(result)
}

#[tauri::command]
pub async fn get_health_detailed() -> Result<DetailedHealthResponse, String> {
    let config = get_config();
    let client = reqwest::Client::new();

    let response = client
        .get(&format!("{}/health/detailed", config.api_base_url))
        .timeout(std::time::Duration::from_secs(10))
        .send()
        .await
        .map_err(|e| format!("Request failed: {}", e))?;

    if !response.status().is_success() {
        return Err(format!("API error: {}", response.status()));
    }

    let result: DetailedHealthResponse = response
        .json()
        .await
        .map_err(|e| format!("Failed to parse response: {}", e))?;

    Ok(result)
}

#[derive(Debug, Serialize, Deserialize)]
pub struct SftpgoStatus {
    pub username: String,
    pub home_dir: String,
    pub files_count: i64,
    pub registered_videos: Vec<RegisteredVideo>,
    pub last_login: Option<String>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct RegisteredVideo {
    pub uuid: String,
    pub file_name: String,
    pub status: String,
}

#[tauri::command]
pub async fn get_sftpgo_status() -> Result<SftpgoStatus, String> {
    let config = get_config();
    let client = reqwest::Client::new();

    let response = client
        .get(&format!("{}/api/v1/stats/sftpgo", config.api_base_url))
        .timeout(std::time::Duration::from_secs(10))
        .send()
        .await
        .map_err(|e| format!("Request failed: {}", e))?;

    if !response.status().is_success() {
        return Err(format!("API error: {}", response.status()));
    }

    let result: SftpgoStatus = response
        .json()
        .await
        .map_err(|e| format!("Failed to parse response: {}", e))?;

    Ok(result)
}

#[derive(Debug, Serialize, Deserialize)]
pub struct InferenceEngineStatus {
    pub engine: String,
    pub model: String,
    pub status: String,
    pub latency_ms: Option<u64>,
    pub error: Option<String>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct InferenceHealthResponse {
    pub ollama: InferenceEngineStatus,
    pub llama_server: InferenceEngineStatus,
}

#[tauri::command]
pub async fn get_inference_health() -> Result<InferenceHealthResponse, String> {
    let config = get_config();
    let client = reqwest::Client::builder()
        .timeout(std::time::Duration::from_secs(5))
        .build()
        .map_err(|e| format!("Client build failed: {}", e))?;

    let response = client
        .get(&format!("{}/api/v1/stats/inference", config.api_base_url))
        .send()
        .await
        .map_err(|e| format!("Request failed: {}", e))?;

    if !response.status().is_success() {
        return Err(format!("API error: {}", response.status()));
    }

    let result: InferenceHealthResponse = response
        .json()
        .await
        .map_err(|e| format!("Failed to parse response: {}", e))?;

    Ok(result)
}

#[tauri::command]
pub fn get_config_info() -> Result<PortalConfig, String> {
    Ok(get_config())
}

#[derive(Debug, Serialize, Deserialize)]
pub struct IngestStats {
    pub total_videos: i64,
    pub total_chunks: i64,
    pub sentence_chunks: i64,
    pub cut_chunks: i64,
    pub time_chunks: i64,
    pub searchable_chunks: i64,
    pub chunks_with_visual: i64,
    pub chunks_with_summary: i64,
    pub pending_videos: i64,
}

#[tauri::command]
pub async fn get_ingest_stats() -> Result<IngestStats, String> {
    let config = get_config();
    let client = reqwest::Client::new();

    let response = client
        .get(&format!("{}/api/v1/stats/ingest", config.api_base_url))
        .timeout(std::time::Duration::from_secs(10))
        .send()
        .await
        .map_err(|e| format!("Request failed: {}", e))?;

    if !response.status().is_success() {
        return Err(format!("API error: {}", response.status()));
    }

    let result: IngestStats = response
        .json()
        .await
        .map_err(|e| format!("Failed to parse response: {}", e))?;

    Ok(result)
}
