mod entangled_system;

use fractal_algebra::FractalGraph;
use rustfft::{FftPlanner, num_complex::Complex};
use entangled_system::{PulseSource, EntangledSystem};
use std::f64::consts::PI;


// --- Data Structures ---
pub struct EntropyPulse {
    pub frequency: f64,
    pub amplitude: f64,
    pub waveform: String,
}
pub struct FeedbackSignal {
    pub correlation_strength: f64,
}
#[derive(Debug, Clone, Copy)]
struct SignalComponent {
    frequency: f64,
    amplitude: f64,
}

// --- The multi-frequency simulation we want to analyze ---
fn run_experiment_multi_frequency(pulse: &EntropyPulse) -> FeedbackSignal {
    const PRIMARY_B: f64 = 1.0;
    const PRIMARY_PHASE: f64 = PI / 2.0;
    let primary_effect = (PRIMARY_B * pulse.frequency - PRIMARY_PHASE).cos();

    const NOISE_B: f64 = 6.2;
    const NOISE_AMPLITUDE: f64 = 0.4;
    const NOISE_PHASE: f64 = 0.7;
    let noise_effect = (NOISE_B * pulse.frequency - NOISE_PHASE).cos() * NOISE_AMPLITUDE;

    let final_correlation = primary_effect + noise_effect;
    FeedbackSignal {
        correlation_strength: final_correlation.clamp(-1.0, 1.0),
    }
}

// --- The CORRECTED FFT Analyzer Function ---
fn fft_analyze_waveform(samples: &[f64], step_size: f64) -> Vec<SignalComponent> {
    let n = samples.len();
    if n == 0 {
        return vec![];
    }

    let mut planner = FftPlanner::new();
    let fft = planner.plan_fft_forward(n);
    let mut buffer: Vec<Complex<f64>> = samples
        .iter()
        .map(|&sample| Complex::new(sample, 0.0))
        .collect();
    fft.process(&mut buffer);

    let mut components = Vec::new();
    for i in 1..(n / 2) {
        let amplitude = buffer[i].norm() * 2.0 / n as f64;

        // *** THIS IS THE CORRECTED LINE ***
        // It now correctly converts the FFT bin index to our 'B' parameter (angular frequency).
        let frequency = (i as f64 * 2.0 * PI) / (n as f64 * step_size);

        if amplitude > 0.05 {
            components.push(SignalComponent {
                frequency,
                amplitude,
            });
        }
    }
    components.sort_by(|a, b| b.amplitude.partial_cmp(&a.amplitude).unwrap());
    components
}


// Process: 
// Create a list of PulseSource objects, 
// pass them to apply_pulses, 
// the system will simulate the resulting interference pattern across the entire graph.
//
// Test:
// Create two PulseSources at different locations.
// Set their phase_offset to be the same (e.g., 0.0).
// Run apply_pulses.
// Check the particle_states. 
// I should see the largest effect (a "hotspot") on the particles that are equidistant 
// from the two sources, where their waves interfere constructively.
fn part4_corrected_test() {
    println!("\n[PART 4] Running a corrected, verifiable test for interference...");

    // 1. Define a graph with a true center point: an 11-node line.
    let num_nodes = 11;
    let mut adjacency_list = vec![vec![]; num_nodes];
    for i in 0..num_nodes {
        if i > 0 {
            adjacency_list[i].push(i - 1);
        }
        if i < num_nodes - 1 {
            adjacency_list[i].push(i + 1);
        }
    }
    println!("[SETUP] Created an {}-node line graph for the test.", num_nodes);

    // Create the system with our defined graph.
    let mut e = EntangledSystem {
        graph: FractalGraph::new(),
        particles: Vec::new(),
        grid_width: num_nodes as u64,
        grid_height: 1,
        adjacency_list,
        particle_states: vec![0.0; num_nodes], // Start all states at 0.
    };

    // 2. Place sources at the new opposite ends.
    let pulse_source_a = PulseSource {
        location_node_index: 0, // Source at the far left
        amplitude: 1.0,
        phase_offset: 0.0,
    };

    let pulse_source_b = PulseSource {
        location_node_index: 10, // Source at the far right
        amplitude: 1.0,
        phase_offset: 0.0,
    };
    println!("[SETUP] Placed sources at nodes 0 and 10.");

    // Run the simulation
    let pulse_sources = vec![pulse_source_a, pulse_source_b];
    e.apply_pulses(&pulse_sources);
    println!("[SIM] Pulses applied. Interference pattern generated.");

    // 3. Automate the verification.
    let mut max_effect = f64::MIN;
    let mut hotspot_node_index = 0;
    for (i, &state) in e.particle_states.iter().enumerate() {
        if state > max_effect {
            max_effect = state;
            hotspot_node_index = i;
        }
    }

    println!("\n--- Test Results ---");
    println!("Raw particle states: {:?}", e.particle_states);
    println!("\n[VERIFY] Hottest spot (max constructive interference) found at Node {}.", hotspot_node_index);
    println!("[VERIFY] Effect strength at hotspot: {:.4}", max_effect);

    // For an 11-node line (0-10), the middle point is 5.
    if hotspot_node_index == 5 {
        println!("\n[SUCCESS] The hotspot is located in the middle, as expected.");
    } else {
        println!("\n[FAILURE] The hotspot is NOT in the middle. Check the logic.");
    }
}

fn main() {
    println!("--- Slow AI 2.0: Scan & Analyze Sequence Initiated ---");

    // === Part 1: High-Resolution Data Acquisition ===
    let num_samples = 256;
    let step_size = 0.05;

    println!(
        "\n[SCAN] Acquiring {} high-resolution data points...",
        num_samples
    );
    let collected_data: Vec<f64> = (0..num_samples)
        .map(|i| {
            let frequency_to_test = i as f64 * step_size;
            let pulse = EntropyPulse {
                frequency: frequency_to_test,
                amplitude: 1.0,
                waveform: "sine".to_string(),
            };
            let feedback = run_experiment_multi_frequency(&pulse);
            feedback.correlation_strength
        })
        .collect();
    println!("[SCAN] Data acquisition complete.");

    // === Part 2: FFT Signal Processing ===
    println!("\n[ANALYZE] Decomposing signal with CORRECTED FFT...");
    // Pass step_size instead of sample_rate, as the new formula uses it directly.
    let components = fft_analyze_waveform(&collected_data, step_size);
    println!("[ANALYZE] Analysis complete.");

    // === Part 3: Conclusion ===
    println!("\n--- AI Signal Analysis Report ---");
    println!("--------------------------------------------------");
    for (i, comp) in components.iter().enumerate() {
        println!(
            "Signal #{}: Frequency (B) = {:.4}, Amplitude = {:.4}",
            i + 1,
            comp.frequency,
            comp.amplitude
        );
    }
    println!("--------------------------------------------------");

    if let Some(primary_signal) = components.first() {
        println!("\nConclusion:");
        println!("✅ The primary signal has been isolated.");
        println!(
            "   The target resonant frequency parameter is B = {:.4}",
            primary_signal.frequency
        );
        if components.len() > 1 {
            println!(
                "   The other {} signals are interfering noise.",
                components.len() - 1
            );
        }
    } else {
        println!("\nConclusion: No significant signals were detected.");
    }

    part4_corrected_test();
}
