// API client module for VAPORA frontend
// Handles all HTTP communication with backend

use gloo_net::http::Request;
// Re-export types from vapora-shared
pub use vapora_shared::models::{Agent, Project, Task, TaskPriority, TaskStatus, Workflow};

use crate::config::AppConfig;

/// API client for backend communication
#[derive(Clone)]
pub struct ApiClient {
    base_url: String,
}

impl ApiClient {
    /// Create new API client with configuration
    pub fn new(config: &AppConfig) -> Self {
        Self {
            base_url: config.api_url.clone(),
        }
    }

    /// Fetch all projects for a tenant
    #[allow(dead_code)]
    pub async fn fetch_projects(&self, tenant_id: &str) -> Result<Vec<Project>, String> {
        let url = format!("{}/api/v1/projects?tenant_id={}", self.base_url, tenant_id);

        Request::get(&url)
            .send()
            .await
            .map_err(|e| format!("Failed to send request: {}", e))?
            .json()
            .await
            .map_err(|e| format!("Failed to parse response: {}", e))
    }

    /// Fetch single project by ID
    #[allow(dead_code)]
    pub async fn fetch_project(&self, project_id: &str) -> Result<Project, String> {
        let url = format!("{}/api/v1/projects/{}", self.base_url, project_id);

        Request::get(&url)
            .send()
            .await
            .map_err(|e| format!("Failed to send request: {}", e))?
            .json()
            .await
            .map_err(|e| format!("Failed to parse response: {}", e))
    }

    /// Create new project
    #[allow(dead_code)]
    pub async fn create_project(&self, project: &Project) -> Result<Project, String> {
        let url = format!("{}/api/v1/projects", self.base_url);
        let body = serde_json::to_string(project).map_err(|e| e.to_string())?;

        Request::post(&url)
            .header("Content-Type", "application/json")
            .body(body)
            .map_err(|e| e.to_string())?
            .send()
            .await
            .map_err(|e| format!("Failed to send request: {}", e))?
            .json()
            .await
            .map_err(|e| format!("Failed to parse response: {}", e))
    }

    /// Fetch all tasks for a project
    pub async fn fetch_tasks(&self, project_id: &str) -> Result<Vec<Task>, String> {
        let url = format!("{}/api/v1/tasks?project_id={}", self.base_url, project_id);

        Request::get(&url)
            .send()
            .await
            .map_err(|e| format!("Failed to send request: {}", e))?
            .json()
            .await
            .map_err(|e| format!("Failed to parse response: {}", e))
    }

    /// Create new task
    #[allow(dead_code)]
    pub async fn create_task(&self, task: &Task) -> Result<Task, String> {
        let url = format!("{}/api/v1/tasks", self.base_url);
        let body = serde_json::to_string(task).map_err(|e| e.to_string())?;

        Request::post(&url)
            .header("Content-Type", "application/json")
            .body(body)
            .map_err(|e| e.to_string())?
            .send()
            .await
            .map_err(|e| format!("Failed to send request: {}", e))?
            .json()
            .await
            .map_err(|e| format!("Failed to parse response: {}", e))
    }

    /// Update task status
    #[allow(dead_code)]
    pub async fn update_task_status(
        &self,
        task_id: &str,
        status: TaskStatus,
    ) -> Result<Task, String> {
        let url = format!("{}/api/v1/tasks/{}", self.base_url, task_id);
        let body = serde_json::json!({ "status": status }).to_string();

        Request::put(&url)
            .header("Content-Type", "application/json")
            .body(body)
            .map_err(|e| e.to_string())?
            .send()
            .await
            .map_err(|e| format!("Failed to send request: {}", e))?
            .json()
            .await
            .map_err(|e| format!("Failed to parse response: {}", e))
    }

    /// Reorder task (drag & drop support)
    #[allow(dead_code)]
    pub async fn reorder_task(
        &self,
        task_id: &str,
        new_order: i32,
        new_status: Option<TaskStatus>,
    ) -> Result<Task, String> {
        let url = format!("{}/api/v1/tasks/{}/reorder", self.base_url, task_id);
        let body = serde_json::json!({
            "task_order": new_order,
            "status": new_status
        })
        .to_string();

        Request::put(&url)
            .header("Content-Type", "application/json")
            .body(body)
            .map_err(|e| e.to_string())?
            .send()
            .await
            .map_err(|e| format!("Failed to send request: {}", e))?
            .json()
            .await
            .map_err(|e| format!("Failed to parse response: {}", e))
    }

    /// Fetch all agents
    pub async fn fetch_agents(&self) -> Result<Vec<Agent>, String> {
        let url = format!("{}/api/v1/agents", self.base_url);

        Request::get(&url)
            .send()
            .await
            .map_err(|e| format!("Failed to send request: {}", e))?
            .json()
            .await
            .map_err(|e| format!("Failed to parse response: {}", e))
    }

    /// Fetch single agent by ID
    #[allow(dead_code)]
    pub async fn fetch_agent(&self, agent_id: &str) -> Result<Agent, String> {
        let url = format!("{}/api/v1/agents/{}", self.base_url, agent_id);

        Request::get(&url)
            .send()
            .await
            .map_err(|e| format!("Failed to send request: {}", e))?
            .json()
            .await
            .map_err(|e| format!("Failed to parse response: {}", e))
    }

    /// Fetch all workflows for a tenant
    #[allow(dead_code)]
    pub async fn fetch_workflows(&self, tenant_id: &str) -> Result<Vec<Workflow>, String> {
        let url = format!("{}/api/v1/workflows?tenant_id={}", self.base_url, tenant_id);

        Request::get(&url)
            .send()
            .await
            .map_err(|e| format!("Failed to send request: {}", e))?
            .json()
            .await
            .map_err(|e| format!("Failed to parse response: {}", e))
    }
}
