//! Tests for dependency module

use governor_core::domain::dependency::{DependencyGraph, WorkspaceDependency};

#[test]
fn test_dependency_graph_creation() {
    let graph = DependencyGraph::new();
    assert_eq!(graph.all_crates().len(), 0);
}

#[test]
fn test_add_dependency() {
    let mut graph = DependencyGraph::new();
    graph.add(WorkspaceDependency::new(
        "crate-a".to_string(),
        "crate-b".to_string(),
        "workspace".to_string(),
    ));

    let deps = graph.dependencies_for("crate-a");
    assert_eq!(deps.len(), 1);
}

#[test]
fn test_no_cycles() {
    let mut graph = DependencyGraph::new();
    graph.add(WorkspaceDependency::new(
        "crate-a".to_string(),
        "crate-b".to_string(),
        "workspace".to_string(),
    ));
    graph.add(WorkspaceDependency::new(
        "crate-b".to_string(),
        "crate-c".to_string(),
        "workspace".to_string(),
    ));

    assert!(!graph.has_cycles());
}

#[test]
fn test_cycle_detection() {
    let mut graph = DependencyGraph::new();
    graph.add(WorkspaceDependency::new(
        "crate-a".to_string(),
        "crate-b".to_string(),
        "workspace".to_string(),
    ));
    graph.add(WorkspaceDependency::new(
        "crate-b".to_string(),
        "crate-c".to_string(),
        "workspace".to_string(),
    ));
    graph.add(WorkspaceDependency::new(
        "crate-c".to_string(),
        "crate-a".to_string(),
        "workspace".to_string(),
    ));

    assert!(graph.has_cycles());
}

#[test]
fn test_publish_order() {
    let mut graph = DependencyGraph::new();
    graph.add(WorkspaceDependency::new(
        "crate-c".to_string(),
        "crate-b".to_string(),
        "workspace".to_string(),
    ));
    graph.add(WorkspaceDependency::new(
        "crate-b".to_string(),
        "crate-a".to_string(),
        "workspace".to_string(),
    ));

    let order = graph.publish_order().unwrap();
    assert_eq!(order, vec!["crate-a", "crate-b", "crate-c"]);
}

#[test]
fn test_workspace_dependency_fields() {
    let dep = WorkspaceDependency::new(
        "my-crate".to_string(),
        "dep-crate".to_string(),
        "workspace".to_string(),
    );
    assert_eq!(dep.from, "my-crate");
    assert_eq!(dep.to, "dep-crate");
}

#[test]
fn test_all_crates() {
    let mut graph = DependencyGraph::new();
    graph.add(WorkspaceDependency::new(
        "crate-a".to_string(),
        "crate-b".to_string(),
        "workspace".to_string(),
    ));
    graph.add(WorkspaceDependency::new(
        "crate-b".to_string(),
        "crate-c".to_string(),
        "workspace".to_string(),
    ));

    let crates = graph.all_crates();
    assert!(crates.contains("crate-a"));
    assert!(crates.contains("crate-b"));
    assert!(crates.contains("crate-c"));
}

#[test]
fn test_dependencies_count() {
    let mut graph = DependencyGraph::new();
    graph.add(WorkspaceDependency::new(
        "crate-a".to_string(),
        "crate-b".to_string(),
        "workspace".to_string(),
    ));
    graph.add(WorkspaceDependency::new(
        "crate-a".to_string(),
        "crate-c".to_string(),
        "workspace".to_string(),
    ));

    let deps = graph.dependencies_for("crate-a");
    assert_eq!(deps.len(), 2);
}

#[test]
fn test_empty_graph() {
    let graph = DependencyGraph::new();
    assert!(!graph.has_cycles());
    let order = graph.publish_order();
    assert!(order.is_ok() || order.is_err());
}
