//! Tests for governor-checkpoint

use governor_checkpoint::FileCheckpointStore;
use governor_core::domain::version::SemanticVersion;
use governor_core::traits::checkpoint_store::{Checkpoint, CheckpointStore};
use tempfile::TempDir;

#[tokio::test]
async fn test_checkpoint_store_save_and_load() {
    let temp_dir = TempDir::new().unwrap();
    let store = FileCheckpointStore::new(temp_dir.path().to_path_buf()).unwrap();

    let checkpoint = Checkpoint::new(
        "workflow-1".to_string(),
        5,
        vec!["step1".to_string(), "step2".to_string()],
        serde_json::json!({"test": "data"}),
    );

    store.save(&checkpoint).await.unwrap();

    let loaded = store.load().await.unwrap().unwrap();
    assert_eq!(loaded.workflow_id, "workflow-1");
    assert_eq!(loaded.step_index, 5);
}

#[tokio::test]
async fn test_checkpoint_store_clear() {
    let temp_dir = TempDir::new().unwrap();
    let store = FileCheckpointStore::new(temp_dir.path().to_path_buf()).unwrap();

    let checkpoint = Checkpoint::new("workflow-1".to_string(), 0, vec![], serde_json::json!({}));

    store.save(&checkpoint).await.unwrap();
    store.clear().await.unwrap();

    let loaded = store.load().await.unwrap();
    assert!(loaded.is_none());
}

#[tokio::test]
async fn test_checkpoint_store_list() {
    let temp_dir = TempDir::new().unwrap();
    let store = FileCheckpointStore::new(temp_dir.path().to_path_buf()).unwrap();

    let checkpoint1 = Checkpoint::new("workflow-1".to_string(), 1, vec![], serde_json::json!({}));

    let checkpoint2 = Checkpoint::new("workflow-1".to_string(), 2, vec![], serde_json::json!({}));

    store.save(&checkpoint1).await.unwrap();
    store.save(&checkpoint2).await.unwrap();

    let list = store.list().await.unwrap();
    assert_eq!(list.len(), 2);
}

#[tokio::test]
async fn test_checkpoint_store_delete() {
    let temp_dir = TempDir::new().unwrap();
    let store = FileCheckpointStore::new(temp_dir.path().to_path_buf()).unwrap();

    let checkpoint = Checkpoint::new("workflow-1".to_string(), 0, vec![], serde_json::json!({}));

    store.save(&checkpoint).await.unwrap();
    store.delete(&checkpoint.id).await.unwrap();

    let loaded = store.load_by_id(&checkpoint.id).await.unwrap();
    assert!(loaded.is_none());
}

#[test]
fn test_checkpoint_serialization() {
    let checkpoint = Checkpoint::new(
        "workflow-1".to_string(),
        0,
        vec!["step1".to_string(), "step2".to_string()],
        serde_json::json!({"key": "value"}),
    );

    let serialized = serde_json::to_string(&checkpoint).unwrap();
    let deserialized: Checkpoint = serde_json::from_str(&serialized).unwrap();

    assert_eq!(deserialized.workflow_id, "workflow-1");
    assert_eq!(deserialized.step_index, 0);
}

#[test]
fn test_checkpoint_with_target_version() {
    let mut checkpoint =
        Checkpoint::new("workflow-1".to_string(), 0, vec![], serde_json::json!(null));
    checkpoint.target_version = Some(SemanticVersion::parse("1.2.3").unwrap());

    assert_eq!(checkpoint.target_version.unwrap().to_string(), "1.2.3");
}

#[test]
fn test_checkpoint_with_error() {
    let mut checkpoint =
        Checkpoint::new("workflow-1".to_string(), 0, vec![], serde_json::json!(null));
    checkpoint.interrupted_by_error = true;
    checkpoint.error_message = Some("Test error".to_string());

    assert!(checkpoint.interrupted_by_error);
    assert_eq!(checkpoint.error_message, Some("Test error".to_string()));
}
