package ai.nektron.grownet.tests;

import ai.nektron.grownet.Layer;
import ai.nektron.grownet.Neuron;
import ai.nektron.grownet.Region;
import ai.nektron.grownet.SlotConfig;
import ai.nektron.grownet.growth.GrowthEngine;
import ai.nektron.grownet.growth.GrowthPolicy;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

public class EffectiveSlotLimitRegressionTests {

    @Test
    void neuronGrowthUsesConfigSlotLimitWhenNeuronOverrideIsUnset() {
        Layer layer = new Layer(1, 0, 0);
        Neuron seedNeuron = layer.getNeurons().get(0);
        SlotConfig slotConfig = seedNeuron.getSlotConfig();
        slotConfig.setSlotLimit(1);
        slotConfig.setGrowthEnabled(true);
        slotConfig.setNeuronGrowthEnabled(true);
        slotConfig.setFallbackGrowthThreshold(1);
        slotConfig.setNeuronGrowthCooldownTicks(0);

        seedNeuron.onInput(0.5);
        seedNeuron.onInput(1.0);

        assertEquals(-1, seedNeuron.getSlotLimit());
        assertEquals(2, layer.getNeurons().size());
    }

    @Test
    void regionGrowthPressureUsesConfigSlotLimitWhenNeuronOverrideIsUnset() {
        Region region = new Region("effective_limit_region");
        int layerIndex = region.addLayer(1, 0, 0);
        Layer donorLayer = region.getLayers().get(layerIndex);
        Neuron donorNeuron = donorLayer.getNeurons().get(0);
        SlotConfig slotConfig = donorNeuron.getSlotConfig();
        slotConfig.setSlotLimit(1);
        slotConfig.setGrowthEnabled(false);
        slotConfig.setNeuronGrowthEnabled(false);

        donorNeuron.onInput(0.5);
        donorNeuron.onInput(1.0);

        GrowthPolicy growthPolicy = new GrowthPolicy()
                .setEnableLayerGrowth(true)
                .setAvgSlotsThreshold(Double.MAX_VALUE)
                .setPercentAtCapFallbackThreshold(50.0)
                .setLayerCooldownTicks(0)
                .setMaxLayers(8)
                .setWireProbability(1.0)
                .setNewLayerExcitatoryCount(2);

        int layerCountBeforeGrowth = region.getLayers().size();
        GrowthEngine.maybeGrow(region, growthPolicy);

        assertTrue(donorNeuron.lastSlotUsedFallback);
        assertEquals(layerCountBeforeGrowth + 1, region.getLayers().size());
    }
}
