/*
    Appellation: vnode <example>
    Contrib: @FL03
*/
extern crate eryon_core as eryon;

use eryon_actors::WolframNode;
use rstmt::prelude::{LPR, Triad};

fn main() -> anyhow::Result<()> {
    // Set up tracing
    tracing_subscriber::fmt()
        .with_max_level(tracing::Level::INFO)
        .init();

    tracing::info!("Advanced VNode Example - Topological Memory Integration");

    // Create a C major triad plant
    let headspace = Triad::major(0); // C-E-G (0,4,7)

    // Create a virtual node with memory
    let mut vnode = WolframNode::<f64>::from_headspace(headspace);

    // Display initial state
    tracing::info!(
        "Node initialized {} features configured with {:?}",
        vnode.total_features(),
        vnode.headspace()
    );

    // Define some critical points
    vnode.identify_critical_point("dominant", 7); // G
    vnode.identify_critical_point("subdominant", 5); // F
    vnode.identify_critical_point("leading_tone", 11); // B

    // Perform a sequence of transformations to establish patterns
    tracing::info!("Performing transformation sequence to establish patterns...");
    let basic_pattern = [LPR::Relative, LPR::Parallel];

    for _ in 0..3 {
        vnode.transform_batch(&basic_pattern)?;
        tracing::info!("Current triad: {:?}", vnode.headspace(),);
    }

    // Check memory statistics
    println!(
        "\n\tMemory statistics:\n\t\t{}\n",
        vnode.get_memory_statistics().generate_report()
    );

    // Predict next move based on learned patterns
    tracing::info!("Predicting next transformation based on patterns:");
    if let Some(next_move) = vnode.predict_next_transformation() {
        tracing::info!("Predicted next move: {:?}", next_move);
    } else {
        tracing::info!("No prediction available");
    }

    // Find possible paths to a triad containing C# (1)
    tracing::info!("Finding paths to C# (1):");
    let paths = vnode.find_paths_to_point(1);

    for (i, path) in paths.iter().enumerate() {
        tracing::info!("  Path {}: {:?}", i + 1, path);
    }

    // Get frequently visited triads
    tracing::info!("Frequently visited triads:");
    let frequent_triads = vnode.get_frequently_visited_triads(2);
    for triad in frequent_triads {
        tracing::info!("{:?} {:?}", triad.class(), triad.notes());
    }

    // Optimize memory
    tracing::info!("Optimizing memory...");
    let stats = vnode.optimize_memory(100)?;
    tracing::info!("Memory optimization results: {stats:?}");
    tracing::info!("  Features after optimization: {}", vnode.total_features());

    // Learn a complex sequence - now using the safer pattern detection
    tracing::info!("Learning complex sequence...");
    let complex_sequence = [LPR::Leading, LPR::Parallel, LPR::Relative, LPR::Leading];
    vnode.learn_transformation_sequence(&complex_sequence)?;

    // Show related triads
    tracing::info!("Triads related to current triad:");
    let related = vnode.find_related_triads();
    for triad in related {
        tracing::info!("  {:?} {:?}", triad.class(), triad.notes());
    }

    // Final memory state
    let final_stats = vnode.get_memory_statistics();
    tracing::info!(
        "Final memory statistics: \n{}",
        final_stats.generate_report()
    );
    // Most common patterns
    tracing::info!("Most common patterns:");
    for (i, (sequence, occurrences)) in final_stats.most_common_patterns().iter().enumerate() {
        let pattern_names: Vec<_> = sequence
            .iter()
            .map(|&id| match id {
                0 => "Leading",
                1 => "Parallel",
                2 => "Relative",
                _ => "Unknown",
            })
            .collect();

        tracing::info!(
            "  Pattern {}: {} occurrences - {:?}",
            i + 1,
            occurrences,
            pattern_names
        );
    }

    Ok(())
}
