use crate::api::orchestrator_types::*;
use gloo_net::http::{Request, RequestBuilder};
use serde_json;
use std::collections::HashMap;
use thiserror::Error;
use url::Url;
use wasm_bindgen_futures::JsFuture;
use web_sys::{console, window};

#[derive(Error, Debug)]
pub enum OrchestratorError {
    #[error("Network error: {0}")]
    Network(String),
    #[error("Serialization error: {0}")]
    Serialization(String),
    #[error("API error: {0}")]
    Api(String),
    #[error("Configuration error: {0}")]
    Config(String),
}

/// Configuration for the orchestrator client
#[derive(Debug, Clone)]
pub struct OrchestratorConfig {
    pub base_url: String,
    pub timeout_seconds: u32,
    pub retry_attempts: u32,
}

impl Default for OrchestratorConfig {
    fn default() -> Self {
        Self {
            base_url: "http://localhost:8080".to_string(),
            timeout_seconds: 30,
            retry_attempts: 3,
        }
    }
}

/// HTTP client for orchestrator API
#[derive(Debug, Clone)]
pub struct OrchestratorClient {
    config: OrchestratorConfig,
}

impl OrchestratorClient {
    /// Create a new orchestrator client with default configuration
    pub fn new() -> Self {
        Self {
            config: OrchestratorConfig::default(),
        }
    }

    /// Create a new orchestrator client with custom configuration
    pub fn with_config(config: OrchestratorConfig) -> Self {
        Self { config }
    }

    /// Build a request with common headers and configuration
    fn build_request(&self, method: &str, path: &str) -> Result<RequestBuilder, OrchestratorError> {
        let url = format!("{}{}", self.config.base_url, path);

        let request = match method.to_uppercase().as_str() {
            "GET" => Request::get(&url),
            "POST" => Request::post(&url),
            "PUT" => Request::put(&url),
            "DELETE" => Request::delete(&url),
            _ => return Err(OrchestratorError::Config(format!("Unsupported HTTP method: {}", method))),
        };

        Ok(request
            .header("Content-Type", "application/json")
            .header("Accept", "application/json"))
    }

    /// Execute a request and parse the response
    async fn execute_request<T>(&self, request: RequestBuilder) -> Result<ApiResponse<T>, OrchestratorError>
    where
        T: serde::de::DeserializeOwned,
    {
        let response = request
            .send()
            .await
            .map_err(|e| OrchestratorError::Network(format!("Request failed: {}", e)))?;

        let status = response.status();
        let response_text = response
            .text()
            .await
            .map_err(|e| OrchestratorError::Network(format!("Failed to read response: {}", e)))?;

        if !status.is_success() {
            return Err(OrchestratorError::Api(format!(
                "HTTP {} - {}",
                status.as_u16(),
                response_text
            )));
        }

        serde_json::from_str::<ApiResponse<T>>(&response_text)
            .map_err(|e| OrchestratorError::Serialization(format!("Failed to parse response: {}", e)))
    }

    /// Execute a request with JSON body
    async fn execute_json_request<T, B>(&self, request: RequestBuilder, body: &B) -> Result<ApiResponse<T>, OrchestratorError>
    where
        T: serde::de::DeserializeOwned,
        B: serde::Serialize,
    {
        let json_body = serde_json::to_string(body)
            .map_err(|e| OrchestratorError::Serialization(format!("Failed to serialize request: {}", e)))?;

        let response = request
            .body(json_body)
            .send()
            .await
            .map_err(|e| OrchestratorError::Network(format!("Request failed: {}", e)))?;

        let status = response.status();
        let response_text = response
            .text()
            .await
            .map_err(|e| OrchestratorError::Network(format!("Failed to read response: {}", e)))?;

        if !status.is_success() {
            return Err(OrchestratorError::Api(format!(
                "HTTP {} - {}",
                status.as_u16(),
                response_text
            )));
        }

        serde_json::from_str::<ApiResponse<T>>(&response_text)
            .map_err(|e| OrchestratorError::Serialization(format!("Failed to parse response: {}", e)))
    }

    // Health and Status Operations

    /// Check orchestrator health
    pub async fn health_check(&self) -> Result<String, OrchestratorError> {
        let request = self.build_request("GET", "/health")?;
        let response = self.execute_request::<String>(request).await?;

        if response.success {
            Ok(response.data.unwrap_or_default())
        } else {
            Err(OrchestratorError::Api(response.error.unwrap_or_default()))
        }
    }

    /// Get system health status
    pub async fn get_system_health(&self) -> Result<SystemHealthStatus, OrchestratorError> {
        let request = self.build_request("GET", "/state/system/health")?;
        let response = self.execute_request::<SystemHealthStatus>(request).await?;

        if response.success {
            Ok(response.data.unwrap())
        } else {
            Err(OrchestratorError::Api(response.error.unwrap_or_default()))
        }
    }

    /// Get system metrics
    pub async fn get_system_metrics(&self) -> Result<SystemMetrics, OrchestratorError> {
        let request = self.build_request("GET", "/state/system/metrics")?;
        let response = self.execute_request::<SystemMetrics>(request).await?;

        if response.success {
            Ok(response.data.unwrap())
        } else {
            Err(OrchestratorError::Api(response.error.unwrap_or_default()))
        }
    }

    // Task Management Operations

    /// List all tasks
    pub async fn list_tasks(&self) -> Result<Vec<WorkflowTask>, OrchestratorError> {
        let request = self.build_request("GET", "/tasks")?;
        let response = self.execute_request::<Vec<WorkflowTask>>(request).await?;

        if response.success {
            Ok(response.data.unwrap_or_default())
        } else {
            Err(OrchestratorError::Api(response.error.unwrap_or_default()))
        }
    }

    /// Get task status by ID
    pub async fn get_task_status(&self, task_id: &str) -> Result<WorkflowTask, OrchestratorError> {
        let request = self.build_request("GET", &format!("/tasks/{}", task_id))?;
        let response = self.execute_request::<WorkflowTask>(request).await?;

        if response.success {
            Ok(response.data.unwrap())
        } else {
            Err(OrchestratorError::Api(response.error.unwrap_or_default()))
        }
    }

    // Workflow Operations

    /// Create server workflow
    pub async fn create_server_workflow(&self, workflow: &CreateServerWorkflow) -> Result<String, OrchestratorError> {
        let request = self.build_request("POST", "/workflows/servers/create")?;
        let response = self.execute_json_request::<String, _>(request, workflow).await?;

        if response.success {
            Ok(response.data.unwrap())
        } else {
            Err(OrchestratorError::Api(response.error.unwrap_or_default()))
        }
    }

    /// Create taskserv workflow
    pub async fn create_taskserv_workflow(&self, workflow: &TaskservWorkflow) -> Result<String, OrchestratorError> {
        let request = self.build_request("POST", "/workflows/taskserv/create")?;
        let response = self.execute_json_request::<String, _>(request, workflow).await?;

        if response.success {
            Ok(response.data.unwrap())
        } else {
            Err(OrchestratorError::Api(response.error.unwrap_or_default()))
        }
    }

    /// Submit a unified component lifecycle operation.
    pub async fn deploy_component(&self, operation: &str, workflow: &ComponentWorkflow) -> Result<String, OrchestratorError> {
        let path = format!("/api/v1/workflows/component/{operation}");
        let request = self.build_request("POST", &path)?;
        let response = self.execute_json_request::<String, _>(request, workflow).await?;

        if response.success {
            Ok(response.data.unwrap_or_default())
        } else {
            Err(OrchestratorError::Api(response.error.unwrap_or_default()))
        }
    }

    /// Create cluster workflow
    pub async fn create_cluster_workflow(&self, workflow: &ClusterWorkflow) -> Result<String, OrchestratorError> {
        let request = self.build_request("POST", "/workflows/cluster/create")?;
        let response = self.execute_json_request::<String, _>(request, workflow).await?;

        if response.success {
            Ok(response.data.unwrap())
        } else {
            Err(OrchestratorError::Api(response.error.unwrap_or_default()))
        }
    }

    // Batch Operations

    /// Execute batch operation
    pub async fn execute_batch_operation(&self, request: &BatchOperationRequest) -> Result<BatchOperationResult, OrchestratorError> {
        let req = self.build_request("POST", "/batch/execute")?;
        let response = self.execute_json_request::<BatchOperationResult, _>(req, request).await?;

        if response.success {
            Ok(response.data.unwrap())
        } else {
            Err(OrchestratorError::Api(response.error.unwrap_or_default()))
        }
    }

    /// List batch operations
    pub async fn list_batch_operations(&self) -> Result<Vec<WorkflowExecutionState>, OrchestratorError> {
        let request = self.build_request("GET", "/batch/operations")?;
        let response = self.execute_request::<Vec<WorkflowExecutionState>>(request).await?;

        if response.success {
            Ok(response.data.unwrap_or_default())
        } else {
            Err(OrchestratorError::Api(response.error.unwrap_or_default()))
        }
    }

    /// Get batch operation status
    pub async fn get_batch_operation_status(&self, operation_id: &str) -> Result<WorkflowExecutionState, OrchestratorError> {
        let request = self.build_request("GET", &format!("/batch/operations/{}", operation_id))?;
        let response = self.execute_request::<WorkflowExecutionState>(request).await?;

        if response.success {
            Ok(response.data.unwrap())
        } else {
            Err(OrchestratorError::Api(response.error.unwrap_or_default()))
        }
    }

    /// Cancel batch operation
    pub async fn cancel_batch_operation(&self, operation_id: &str) -> Result<String, OrchestratorError> {
        let request = self.build_request("POST", &format!("/batch/operations/{}/cancel", operation_id))?;
        let response = self.execute_request::<String>(request).await?;

        if response.success {
            Ok(response.data.unwrap())
        } else {
            Err(OrchestratorError::Api(response.error.unwrap_or_default()))
        }
    }

    // Progress Tracking

    /// Get workflow progress
    pub async fn get_workflow_progress(&self, workflow_id: &str) -> Result<ProgressInfo, OrchestratorError> {
        let request = self.build_request("GET", &format!("/state/workflows/{}/progress", workflow_id))?;
        let response = self.execute_request::<ProgressInfo>(request).await?;

        if response.success {
            Ok(response.data.unwrap())
        } else {
            Err(OrchestratorError::Api(response.error.unwrap_or_default()))
        }
    }

    /// Get workflow snapshots
    pub async fn get_workflow_snapshots(&self, workflow_id: &str) -> Result<Vec<StateSnapshot>, OrchestratorError> {
        let request = self.build_request("GET", &format!("/state/workflows/{}/snapshots", workflow_id))?;
        let response = self.execute_request::<Vec<StateSnapshot>>(request).await?;

        if response.success {
            Ok(response.data.unwrap_or_default())
        } else {
            Err(OrchestratorError::Api(response.error.unwrap_or_default()))
        }
    }

    // Rollback Operations

    /// Create checkpoint
    pub async fn create_checkpoint(&self, request: &CreateCheckpointRequest) -> Result<String, OrchestratorError> {
        let req = self.build_request("POST", "/rollback/checkpoints")?;
        let response = self.execute_json_request::<String, _>(req, request).await?;

        if response.success {
            Ok(response.data.unwrap())
        } else {
            Err(OrchestratorError::Api(response.error.unwrap_or_default()))
        }
    }

    /// List checkpoints
    pub async fn list_checkpoints(&self) -> Result<Vec<Checkpoint>, OrchestratorError> {
        let request = self.build_request("GET", "/rollback/checkpoints")?;
        let response = self.execute_request::<Vec<Checkpoint>>(request).await?;

        if response.success {
            Ok(response.data.unwrap_or_default())
        } else {
            Err(OrchestratorError::Api(response.error.unwrap_or_default()))
        }
    }

    /// Get checkpoint by ID
    pub async fn get_checkpoint(&self, checkpoint_id: &str) -> Result<Checkpoint, OrchestratorError> {
        let request = self.build_request("GET", &format!("/rollback/checkpoints/{}", checkpoint_id))?;
        let response = self.execute_request::<Checkpoint>(request).await?;

        if response.success {
            Ok(response.data.unwrap())
        } else {
            Err(OrchestratorError::Api(response.error.unwrap_or_default()))
        }
    }

    /// Execute rollback
    pub async fn execute_rollback(&self, request: &RollbackRequest) -> Result<RollbackResult, OrchestratorError> {
        let req = self.build_request("POST", "/rollback/execute")?;
        let response = self.execute_json_request::<RollbackResult, _>(req, request).await?;

        if response.success {
            Ok(response.data.unwrap())
        } else {
            Err(OrchestratorError::Api(response.error.unwrap_or_default()))
        }
    }

    /// Get rollback statistics
    pub async fn get_rollback_statistics(&self) -> Result<RollbackStatistics, OrchestratorError> {
        let request = self.build_request("GET", "/rollback/statistics")?;
        let response = self.execute_request::<RollbackStatistics>(request).await?;

        if response.success {
            Ok(response.data.unwrap())
        } else {
            Err(OrchestratorError::Api(response.error.unwrap_or_default()))
        }
    }

    /// Restore from checkpoint
    pub async fn restore_from_checkpoint(&self, checkpoint_id: &str) -> Result<String, OrchestratorError> {
        let request = self.build_request("POST", &format!("/rollback/restore/{}", checkpoint_id))?;
        let response = self.execute_request::<String>(request).await?;

        if response.success {
            Ok(response.data.unwrap())
        } else {
            Err(OrchestratorError::Api(response.error.unwrap_or_default()))
        }
    }

    // State Management

    /// Get state statistics
    pub async fn get_state_statistics(&self) -> Result<StateManagerStatistics, OrchestratorError> {
        let request = self.build_request("GET", "/state/statistics")?;
        let response = self.execute_request::<StateManagerStatistics>(request).await?;

        if response.success {
            Ok(response.data.unwrap())
        } else {
            Err(OrchestratorError::Api(response.error.unwrap_or_default()))
        }
    }
}

impl Default for OrchestratorClient {
    fn default() -> Self {
        Self::new()
    }
}
