import networkx as nx
import matplotlib.pyplot as plt
#--------------------------------------------------------------------------------------------------
def create_and_visualize_properties_graph():
    """
    Creates an attributed graph using networkx and visualizes it using matplotlib.
    Nodes have 'role' and 'age' properties.
    Edges have a 'weight' property.
    """
    # 1. Initialize an empty Graph object
    G = nx.DiGraph()

    # --- 2. Add Nodes with Properties (Attributes) ---
    # Node properties are passed as keyword arguments (role, age)
    G.add_node("Alice", role="Manager", age=45, color='skyblue')
    G.add_node("Bob", role="Developer", age=30, color='lightgreen')
    G.add_node("Charlie", role="Developer", age=35, color='lightgreen')
    G.add_node("David", role="Intern", age=22, color='lightcoral')

    # --- 3. Add Edges with Properties (Attributes) ---
    # Edge properties are passed after the node tuple
    # Alice manages Bob (weight 0.8: strong link)
    G.add_edge("Alice", "Bob", relationship="Manages", weight=0.8)
    # Alice collaborates with Charlie (weight 0.5: medium link)
    G.add_edge("Alice", "Charlie", relationship="Collaborates", weight=0.5)
    # Bob mentors David (weight 1.0: very strong link)
    G.add_edge("Bob", "David", relationship="Mentors", weight=1.0)
    # Charlie and David have a weak link (0.2)
    G.add_edge("Charlie", "David", relationship="WorksWith", weight=0.2)
    G.add_edge("David", "Charlie", relationship="WorksWith", weight=0.2)

    print("--- Graph Data ---")
    print(f"Nodes: {G.nodes(data=True)}")
    print(f"Edges: {G.edges(data=True)}")
    print("-" * 20)

    # --- 4. Visualization Setup ---
    # Use a spring layout for visualization (looks like a network)
    pos = nx.spring_layout(G, seed=42)
    # Prepare node colors and sizes from node attributes
    node_colors = [data['color'] for _, data in G.nodes(data=True)]
    # Scale node size based on age (for visual distinction)
    node_sizes = [data['age'] * 10 for _, data in G.nodes(data=True)]
    # Prepare edge widths based on 'weight' attribute
    edge_weights = [data['weight'] * 5 for _, __, data in G.edges(data=True)]
    # Prepare labels for visualization
    # Node labels show the node ID and its role property
    node_labels = {node: f"{node}\n({G.nodes[node]['role']})" for node in G.nodes()}
    # Edge labels show the relationship property
    edge_labels = nx.get_edge_attributes(G, 'relationship')

    # --- 5. Draw the Graph ---
    plt.figure(figsize=(10, 7))
    plt.title("Attributed Knowledge Graph (NetworkX)")
    # Draw Nodes
    nx.draw_networkx_nodes(G, pos, 
                           node_color=node_colors, 
                           node_size=node_sizes, 
                           alpha=0.9,
                           edgecolors='gray')
    # Draw Edges
    nx.draw_networkx_edges(G, pos, 
                           width=edge_weights,
                           arrowsize=20,
                           alpha=0.6, 
                           edge_color='gray')
    # Draw Node Labels
    nx.draw_networkx_labels(G, pos, 
                            labels=node_labels, 
                            font_size=10, 
                            font_color="black")
    # Draw Edge Labels (Relationships)
    nx.draw_networkx_edge_labels(G, pos, 
                                 edge_labels=edge_labels, 
                                 font_color='red', 
                                 font_size=9)
    # Show the plot
    plt.axis('off')
    plt.show()
#--------------------------------------------------------------------------------------------------
if __name__ == "__main__":
    # Ensure NetworkX and Matplotlib are installed before running:
    # pip install networkx matplotlib
    create_and_visualize_properties_graph()
#--------------------------------------------------------------------------------------------------
