// NOTE: These tests use the old serialization API. They need to be updated to use:
// - FeagiByteContainer instead of FeagiByteStructure
// - FeagiSerializable trait instead of FeagiByteStructureCompatible
// - get_number_of_bytes_needed() instead of max_number_bytes_needed()
// - overwrite_byte_data_with_single_struct_data() instead of as_new_feagi_byte_structure()
// TODO: Update tests to use new serialization API
use feagi_serialization::{FeagiByteContainer, FeagiByteStructureType, FeagiSerializable};
use feagi_structures::genomic::cortical_area::CoreCorticalType;
use feagi_structures::neuron_voxels::xyzp::{
    CorticalMappedXYZPNeuronVoxels, NeuronVoxelXYZP, NeuronVoxelXYZPArrays,
};
use ndarray::prelude::*;

#[test]
fn test_minimal_memory_corruption_debug() {
    // Create a simple test case
    let cortical_id = CoreCorticalType::Power.to_cortical_id();
    let neuron = NeuronVoxelXYZP::new(1, 2, 3, 0.5);
    let mut neurons = NeuronVoxelXYZPArrays::with_capacity(1);
    neurons.push(&neuron);

    let mut cortical_mappings = CorticalMappedXYZPNeuronVoxels::new();
    cortical_mappings.insert(cortical_id, neurons);

    // Test 1: Check if get_number_of_bytes_needed is consistent
    let size1 = cortical_mappings.get_number_of_bytes_needed();
    let size2 = cortical_mappings.get_number_of_bytes_needed();
    println!("Size check: {} == {}", size1, size2);
    assert_eq!(size1, size2);

    // Test 2-5: Serialize using new API
    let mut container = FeagiByteContainer::new_empty();
    container
        .overwrite_byte_data_with_single_struct_data(&cortical_mappings, 0)
        .unwrap();
    let bytes = container.get_byte_ref().to_vec();
    assert!(!bytes.is_empty());
}

#[test]
#[allow(unused_variables, dead_code, unreachable_code)]
fn test_serialize_deserialize_neuron_mapped_areas() {
    // cortical area A
    let cortical_id_a = CoreCorticalType::Power.to_cortical_id();
    let neuron_a_1 = NeuronVoxelXYZP::new(1, 2, 3, 0.5);
    let neuron_a_2 = NeuronVoxelXYZP::new(4, 5, 7, 0.2);
    let mut neurons_a = NeuronVoxelXYZPArrays::with_capacity(2); // lets preallocate
    neurons_a.push(&neuron_a_1);
    neurons_a.push(&neuron_a_2);

    // cortical area b
    let cortical_id_b = CoreCorticalType::Death.to_cortical_id();
    let neuron_b_1 = NeuronVoxelXYZP::new(8, 9, 10, 0.5);
    let neuron_b_2 = NeuronVoxelXYZP::new(11, 12, 13, 0.2);
    let mut neurons_b = NeuronVoxelXYZPArrays::with_capacity(1); // incorrect preallocation (system should grow)
    neurons_b.push(&neuron_b_1);
    neurons_b.push(&neuron_b_2);

    assert_eq!(neurons_a.len(), neurons_b.len());

    // lets add cortical are C using arrays
    let cortical_id_c = CoreCorticalType::Fatigue.to_cortical_id();
    let neurons_c_x = array![1, 2, 3];
    let neurons_c_y = array![4, 5, 6];
    let neurons_c_z = array![7, 8, 9];
    let neurons_c_p: Array<f32, Ix1> = array![0.1, 0.2, 0.3];
    let neurons_c = NeuronVoxelXYZPArrays::new_from_ndarrays(
        neurons_c_x,
        neurons_c_y,
        neurons_c_z,
        neurons_c_p,
    )
    .unwrap();

    // cortical mappings
    let mut cortical_mappings = CorticalMappedXYZPNeuronVoxels::new();
    cortical_mappings.insert(cortical_id_a, neurons_a);
    cortical_mappings.insert(cortical_id_b, neurons_b);
    cortical_mappings.insert(cortical_id_c, neurons_c);

    // bytes data serialization
    let mut sending_container = FeagiByteContainer::new_empty();
    sending_container
        .overwrite_byte_data_with_single_struct_data(&cortical_mappings, 0)
        .unwrap();
    let bytes = sending_container.get_byte_ref().to_vec(); // raw bytes

    // deserialize (lets pretend 'bytes' was sent over the network)
    let received_boxed = {
        let mut received_container = FeagiByteContainer::new_empty();
        received_container
            .try_write_data_by_ownership_to_container_and_verify(bytes)
            .unwrap();
        received_container
            .try_create_struct_from_first_found_struct_of_type(
                FeagiByteStructureType::NeuronCategoricalXYZP,
            )
            .unwrap()
            .unwrap()
    };
    let received_cortical_mappings =
        CorticalMappedXYZPNeuronVoxels::try_from(received_boxed).unwrap();

    assert_eq!(received_cortical_mappings.len(), 3);
    assert!(received_cortical_mappings.contains_cortical_id(&cortical_id_a));
    assert!(received_cortical_mappings.contains_cortical_id(&cortical_id_b));
    assert!(received_cortical_mappings.contains_cortical_id(&cortical_id_c));

    let rec_neurons_a = received_cortical_mappings
        .get_neurons_of(&cortical_id_a)
        .unwrap();
    let rec_neurons_b = received_cortical_mappings
        .get_neurons_of(&cortical_id_b)
        .unwrap();

    let rec_neuron_1_a = rec_neurons_a.copy_as_neuron_xyzp_vec()[0].clone();
    let rec_neuron_2_b = rec_neurons_b.copy_as_neuron_xyzp_vec()[1].clone();

    assert_eq!(rec_neuron_1_a, neuron_a_1);
    assert_eq!(rec_neuron_2_b, neuron_b_2);
}
