/// System Status API Client
///
/// Provides functions to check system prerequisites, workspace configuration,
/// and infrastructure status for the onboarding flow.
use gloo_net::http::Request;
use serde::{Deserialize, Serialize};

use crate::config::use_config;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SystemStatusResponse {
    pub nushell_installed: bool,
    pub nushell_version: Option<String>,
    pub workspace_configured: bool,
    pub workspace_name: Option<String>,
    pub servers_deployed: bool,
    pub server_count: usize,
    pub taskservs_installed: bool,
    pub taskserv_count: usize,
    pub orchestrator_running: bool,
    pub orchestrator_version: Option<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PrerequisiteCheck {
    pub name: String,
    pub installed: bool,
    pub version: Option<String>,
    pub required_version: String,
    pub install_command: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PrerequisitesResponse {
    pub checks: Vec<PrerequisiteCheck>,
    pub all_satisfied: bool,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NextStepRecommendation {
    pub id: String,
    pub title: String,
    pub description: String,
    pub priority: usize,
    pub action_url: String,
    pub action_type: String, // "navigate", "api_call", "external"
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NextStepsResponse {
    pub recommendations: Vec<NextStepRecommendation>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DocSearchQuery {
    pub query: String,
    pub limit: Option<usize>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DocSearchResult {
    pub title: String,
    pub url: String,
    pub excerpt: String,
    pub category: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DocSearchResponse {
    pub results: Vec<DocSearchResult>,
    pub total: usize,
}

/// Fetch overall system status
pub async fn fetch_system_status() -> Result<SystemStatusResponse, String> {
    let config = use_config();
    let url = format!("{}/api/system/status", config.api.orchestrator_url);

    match Request::get(&url).send().await {
        Ok(response) => {
            if response.ok() {
                response
                    .json::<SystemStatusResponse>()
                    .await
                    .map_err(|e| format!("Failed to parse system status: {}", e))
            } else {
                // If endpoint doesn't exist yet, return default status
                Ok(SystemStatusResponse {
                    nushell_installed: true, // Assume true if UI is running
                    nushell_version: Some("0.107.1".to_string()),
                    workspace_configured: false,
                    workspace_name: None,
                    servers_deployed: false,
                    server_count: 0,
                    taskservs_installed: false,
                    taskserv_count: 0,
                    orchestrator_running: true, // If we got a response
                    orchestrator_version: Some("1.0.0".to_string()),
                })
            }
        }
        Err(e) => Err(format!("Failed to fetch system status: {}", e)),
    }
}

/// Check system prerequisites
pub async fn check_prerequisites() -> Result<PrerequisitesResponse, String> {
    let config = use_config();
    let url = format!("{}/api/system/prerequisites", config.api.orchestrator_url);

    match Request::get(&url).send().await {
        Ok(response) => {
            if response.ok() {
                response
                    .json::<PrerequisitesResponse>()
                    .await
                    .map_err(|e| format!("Failed to parse prerequisites: {}", e))
            } else {
                // Return default prerequisites if endpoint doesn't exist
                Ok(PrerequisitesResponse {
                    checks: vec![
                        PrerequisiteCheck {
                            name: "Nushell".to_string(),
                            installed: true,
                            version: Some("0.107.1".to_string()),
                            required_version: "0.107.1+".to_string(),
                            install_command: "brew install nushell".to_string(),
                        },
                        PrerequisiteCheck {
                            name: "Docker".to_string(),
                            installed: false,
                            version: None,
                            required_version: "20.10+".to_string(),
                            install_command: "brew install docker".to_string(),
                        },
                        PrerequisiteCheck {
                            name: "KCL".to_string(),
                            installed: false,
                            version: None,
                            required_version: "0.11.2+".to_string(),
                            install_command: "brew install kcl".to_string(),
                        },
                    ],
                    all_satisfied: false,
                })
            }
        }
        Err(e) => Err(format!("Failed to check prerequisites: {}", e)),
    }
}

/// Get next step recommendations
pub async fn get_next_steps() -> Result<NextStepsResponse, String> {
    let config = use_config();
    let url = format!("{}/api/system/next-steps", config.api.orchestrator_url);

    match Request::get(&url).send().await {
        Ok(response) => {
            if response.ok() {
                response
                    .json::<NextStepsResponse>()
                    .await
                    .map_err(|e| format!("Failed to parse next steps: {}", e))
            } else {
                // Return default recommendations
                Ok(NextStepsResponse {
                    recommendations: vec![
                        NextStepRecommendation {
                            id: "create-workspace".to_string(),
                            title: "Create Your First Workspace".to_string(),
                            description: "Set up a workspace to organize your infrastructure"
                                .to_string(),
                            priority: 1,
                            action_url: "/settings".to_string(),
                            action_type: "navigate".to_string(),
                        },
                        NextStepRecommendation {
                            id: "deploy-server".to_string(),
                            title: "Deploy Your First Server".to_string(),
                            description: "Create cloud servers to host your infrastructure"
                                .to_string(),
                            priority: 2,
                            action_url: "/servers".to_string(),
                            action_type: "navigate".to_string(),
                        },
                    ],
                })
            }
        }
        Err(e) => Err(format!("Failed to fetch next steps: {}", e)),
    }
}

/// Search documentation
pub async fn search_docs(query: &str, limit: Option<usize>) -> Result<DocSearchResponse, String> {
    let config = use_config();
    // Simple URL encoding (replace spaces with %20)
    let encoded_query = query.replace(" ", "%20");
    let url = format!(
        "{}/api/docs/search?q={}&limit={}",
        config.api.orchestrator_url,
        encoded_query,
        limit.unwrap_or(10)
    );

    match Request::get(&url).send().await {
        Ok(response) => {
            if response.ok() {
                response
                    .json::<DocSearchResponse>()
                    .await
                    .map_err(|e| format!("Failed to parse search results: {}", e))
            } else {
                // Return empty results if endpoint doesn't exist
                Ok(DocSearchResponse {
                    results: vec![],
                    total: 0,
                })
            }
        }
        Err(e) => Err(format!("Failed to search docs: {}", e)),
    }
}

/// Check if workspace exists and is configured
pub async fn check_workspace() -> Result<bool, String> {
    let config = use_config();
    let url = format!("{}/api/workspace/status", config.api.orchestrator_url);

    match Request::get(&url).send().await {
        Ok(response) => {
            if response.ok() {
                #[derive(Deserialize)]
                struct WorkspaceStatus {
                    configured: bool,
                }
                response
                    .json::<WorkspaceStatus>()
                    .await
                    .map(|s| s.configured)
                    .map_err(|e| format!("Failed to parse workspace status: {}", e))
            } else {
                Ok(false)
            }
        }
        Err(_) => Ok(false),
    }
}

/// Check if servers are deployed
pub async fn check_servers() -> Result<usize, String> {
    let config = use_config();
    let url = format!("{}/api/servers", config.api.orchestrator_url);

    match Request::get(&url).send().await {
        Ok(response) => {
            if response.ok() {
                #[derive(Deserialize)]
                struct ServerList {
                    servers: Vec<serde_json::Value>,
                }
                response
                    .json::<ServerList>()
                    .await
                    .map(|s| s.servers.len())
                    .map_err(|e| format!("Failed to parse servers: {}", e))
            } else {
                Ok(0)
            }
        }
        Err(_) => Ok(0),
    }
}

/// Check if taskservs are installed
pub async fn check_taskservs() -> Result<usize, String> {
    let config = use_config();
    let url = format!("{}/api/taskservs", config.api.orchestrator_url);

    match Request::get(&url).send().await {
        Ok(response) => {
            if response.ok() {
                #[derive(Deserialize)]
                struct TaskservList {
                    taskservs: Vec<serde_json::Value>,
                }
                response
                    .json::<TaskservList>()
                    .await
                    .map(|s| s.taskservs.len())
                    .map_err(|e| format!("Failed to parse taskservs: {}", e))
            } else {
                Ok(0)
            }
        }
        Err(_) => Ok(0),
    }
}

/// Get orchestrator diagnostics
pub async fn get_orchestrator_diagnostics() -> Result<serde_json::Value, String> {
    let config = use_config();
    let url = format!("{}/api/system/diagnostics", config.api.orchestrator_url);

    match Request::get(&url).send().await {
        Ok(response) => {
            if response.ok() {
                response
                    .json::<serde_json::Value>()
                    .await
                    .map_err(|e| format!("Failed to parse diagnostics: {}", e))
            } else {
                Err(format!(
                    "Diagnostics endpoint returned: {}",
                    response.status()
                ))
            }
        }
        Err(e) => Err(format!("Failed to fetch diagnostics: {}", e)),
    }
}
