//! Basic tests for SurrealDB storage implementation
//!
//! These tests verify that the SurrealDB storage backend can be created
//! and basic operations work correctly.

#[cfg(test)]
#[cfg(feature = "surrealdb")]
mod tests {
    use chrono::Utc;
    use tempfile::TempDir;
    use uuid::Uuid;

    use super::super::surrealdb::SurrealStorage;
    use super::super::traits::TaskStorage;
    use crate::{TaskStatus, WorkflowTask};

    /// Create a test task
    fn create_test_task(name: &str) -> WorkflowTask {
        WorkflowTask {
            id: Uuid::new_v4().to_string(),
            name: name.to_string(),
            command: "echo".to_string(),
            args: vec!["hello".to_string()],
            dependencies: vec![],
            status: TaskStatus::Pending,
            created_at: Utc::now(),
            started_at: None,
            completed_at: None,
            output: None,
            error: None,
        }
    }

    #[tokio::test]
    async fn test_storage_creation() {
        // Create temporary directory for embedded database
        let temp_dir = TempDir::new().expect("Failed to create temp dir");
        let db_path = temp_dir.path().join("test.db");

        let _storage = SurrealStorage::embedded(db_path.to_str().unwrap());
        // Storage creation succeeds if we get here
    }

    #[tokio::test]
    async fn test_storage_initialization() {
        let temp_dir = TempDir::new().expect("Failed to create temp dir");
        let db_path = temp_dir.path().join("test_init.db");

        let storage = SurrealStorage::embedded(db_path.to_str().unwrap());

        // Initialize should succeed
        assert!(storage.init().await.is_ok());

        // Health check should pass
        assert!(storage.health_check().await.unwrap());
    }

    #[tokio::test]
    async fn test_basic_task_operations() {
        let temp_dir = TempDir::new().expect("Failed to create temp dir");
        let db_path = temp_dir.path().join("test_ops.db");

        let storage = SurrealStorage::embedded(db_path.to_str().unwrap());
        storage.init().await.expect("Failed to initialize storage");

        let test_task = create_test_task("test_task");
        let task_id = test_task.id.clone();

        // Test enqueue
        assert!(storage.enqueue(test_task.clone(), 1).await.is_ok());

        // Test queue size
        let queue_size = storage
            .queue_size()
            .await
            .expect("Failed to get queue size");
        assert!(queue_size > 0);

        // Test peek (should not remove from queue)
        let peeked = storage.peek().await.expect("Failed to peek");
        assert!(peeked.is_some());

        // Queue size should still be the same
        let queue_size_after_peek = storage
            .queue_size()
            .await
            .expect("Failed to get queue size");
        assert_eq!(queue_size, queue_size_after_peek);

        // Test get_task
        let retrieved = storage
            .get_task(&task_id)
            .await
            .expect("Failed to get task");
        assert!(retrieved.is_some());
        assert_eq!(retrieved.unwrap().name, test_task.name);

        // Test dequeue
        let dequeued = storage.dequeue().await.expect("Failed to dequeue");
        assert!(dequeued.is_some());
        assert_eq!(dequeued.unwrap().name, test_task.name);

        // Queue should now be empty
        let final_queue_size = storage
            .queue_size()
            .await
            .expect("Failed to get queue size");
        assert_eq!(final_queue_size, 0);
    }

    #[tokio::test]
    async fn test_task_status_update() {
        let temp_dir = TempDir::new().expect("Failed to create temp dir");
        let db_path = temp_dir.path().join("test_status.db");

        let storage = SurrealStorage::embedded(db_path.to_str().unwrap());
        storage.init().await.expect("Failed to initialize storage");

        let test_task = create_test_task("status_test");
        let task_id = test_task.id.clone();

        // Enqueue task
        storage
            .enqueue(test_task, 1)
            .await
            .expect("Failed to enqueue");

        // Update status to Running
        storage
            .update_task_status(&task_id, TaskStatus::Running)
            .await
            .expect("Failed to update status");

        // Verify status was updated
        let updated_task = storage
            .get_task(&task_id)
            .await
            .expect("Failed to get task")
            .expect("Task not found");

        assert_eq!(updated_task.status, TaskStatus::Running);
    }

    #[tokio::test]
    async fn test_list_tasks_with_filter() {
        let temp_dir = TempDir::new().expect("Failed to create temp dir");
        let db_path = temp_dir.path().join("test_list.db");

        let storage = SurrealStorage::embedded(db_path.to_str().unwrap());
        storage.init().await.expect("Failed to initialize storage");

        // Create and enqueue multiple tasks
        let task1 = create_test_task("task1");
        let task2 = create_test_task("task2");
        let task1_id = task1.id.clone();

        storage
            .enqueue(task1, 1)
            .await
            .expect("Failed to enqueue task1");
        storage
            .enqueue(task2, 2)
            .await
            .expect("Failed to enqueue task2");

        // Update one task to Running
        storage
            .update_task_status(&task1_id, TaskStatus::Running)
            .await
            .expect("Failed to update status");

        // List all tasks
        let all_tasks = storage
            .list_tasks(None)
            .await
            .expect("Failed to list all tasks");
        assert!(all_tasks.len() >= 2);

        // List only pending tasks
        let pending_tasks = storage
            .list_tasks(Some(TaskStatus::Pending))
            .await
            .expect("Failed to list pending tasks");
        assert!(!pending_tasks.is_empty());
        assert!(pending_tasks
            .iter()
            .all(|t| t.status == TaskStatus::Pending));

        // List only running tasks
        let running_tasks = storage
            .list_tasks(Some(TaskStatus::Running))
            .await
            .expect("Failed to list running tasks");
        assert!(!running_tasks.is_empty());
        assert!(running_tasks
            .iter()
            .all(|t| t.status == TaskStatus::Running));
    }

    #[tokio::test]
    async fn test_statistics() {
        let temp_dir = TempDir::new().expect("Failed to create temp dir");
        let db_path = temp_dir.path().join("test_stats.db");

        let storage = SurrealStorage::embedded(db_path.to_str().unwrap());
        storage.init().await.expect("Failed to initialize storage");

        // Initially, all counts should be zero
        let initial_stats = storage
            .get_statistics()
            .await
            .expect("Failed to get statistics");
        assert_eq!(initial_stats.total_tasks, 0);

        // Add some tasks
        let task1 = create_test_task("stats_task1");
        let task2 = create_test_task("stats_task2");
        let task1_id = task1.id.clone();

        storage
            .enqueue(task1, 1)
            .await
            .expect("Failed to enqueue task1");
        storage
            .enqueue(task2, 1)
            .await
            .expect("Failed to enqueue task2");

        // Update one task to completed
        storage
            .update_task_status(&task1_id, TaskStatus::Completed)
            .await
            .expect("Failed to update status");

        // Check updated statistics
        let updated_stats = storage
            .get_statistics()
            .await
            .expect("Failed to get statistics");
        assert!(updated_stats.total_tasks >= 2);
        assert!(updated_stats.completed_tasks >= 1);
        assert!(updated_stats.pending_tasks >= 1);
        assert!(updated_stats.uptime.num_seconds() >= 0);
    }
}
