package com.livingworld.modules.pollution;

import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

class PollutionRegionDataTest {

    @Test
    void defaultsHaveZeroPollution() {
        PollutionRegionData d = PollutionRegionData.defaults();
        assertEquals(0.0,  d.getAirPollution(),    1e-9);
        assertEquals(0.0,  d.getGroundPollution(), 1e-9);
        assertEquals(0.0,  d.getWaterPollution(),  1e-9);
        assertEquals(20.0, d.getDecayResistance(), 1e-9);
    }

    @Test
    void addPollutionAccumulates() {
        PollutionRegionData d = PollutionRegionData.defaults();
        d.addPollution(10.0, 20.0, 5.0);
        assertEquals(10.0, d.getAirPollution(),    1e-9);
        assertEquals(20.0, d.getGroundPollution(), 1e-9);
        assertEquals(5.0,  d.getWaterPollution(),  1e-9);
    }

    @Test
    void addPollutionClampsAt100() {
        PollutionRegionData d = new PollutionRegionData(90.0, 90.0, 90.0, 20.0);
        d.addPollution(20.0, 20.0, 20.0);
        assertEquals(100.0, d.getAirPollution(),    1e-9);
        assertEquals(100.0, d.getGroundPollution(), 1e-9);
        assertEquals(100.0, d.getWaterPollution(),  1e-9);
    }

    @Test
    void decayReducesAllPollution() {
        PollutionRegionData d = new PollutionRegionData(50.0, 50.0, 50.0, 0.0);
        d.decay(0.02);
        // With zero resistance: effectiveRate = 0.02 * 1.0 = 0.02
        // air:    50 * (1 - 0.04) = 48
        // ground: 50 * (1 - 0.01) = 49.5
        // water:  50 * (1 - 0.006) = 49.7
        assertTrue(d.getAirPollution()    < 50.0);
        assertTrue(d.getGroundPollution() < 50.0);
        assertTrue(d.getWaterPollution()  < 50.0);
    }

    @Test
    void decayWithHighResistanceIsSlower() {
        PollutionRegionData low  = new PollutionRegionData(50.0, 50.0, 50.0, 0.0);
        PollutionRegionData high = new PollutionRegionData(50.0, 50.0, 50.0, 100.0);
        low.decay(0.02);
        high.decay(0.02);
        assertTrue(high.getAirPollution() > low.getAirPollution(),
                "High resistance should leave more air pollution after decay");
    }

    @Test
    void decayOnZeroPollutionStaysZero() {
        PollutionRegionData d = PollutionRegionData.defaults();
        d.decay(0.10);
        assertEquals(0.0, d.getAirPollution(),    1e-9);
        assertEquals(0.0, d.getGroundPollution(), 1e-9);
        assertEquals(0.0, d.getWaterPollution(),  1e-9);
    }

    @Test
    void constructorClampsNegativeValues() {
        PollutionRegionData d = new PollutionRegionData(-10.0, -5.0, -1.0, -50.0);
        assertEquals(0.0, d.getAirPollution(),    1e-9);
        assertEquals(0.0, d.getGroundPollution(), 1e-9);
        assertEquals(0.0, d.getWaterPollution(),  1e-9);
        assertEquals(0.0, d.getDecayResistance(), 1e-9);
    }

    @Test
    void constructorClampsAbove100() {
        PollutionRegionData d = new PollutionRegionData(200.0, 150.0, 110.0, 999.0);
        assertEquals(100.0, d.getAirPollution(),    1e-9);
        assertEquals(100.0, d.getGroundPollution(), 1e-9);
        assertEquals(100.0, d.getWaterPollution(),  1e-9);
        assertEquals(100.0, d.getDecayResistance(), 1e-9);
    }

    @Test
    void copyIsIndependent() {
        PollutionRegionData original = new PollutionRegionData(30.0, 40.0, 10.0, 25.0);
        PollutionRegionData copy = original.copy();
        copy.addPollution(50.0, 50.0, 50.0);
        assertEquals(30.0, original.getAirPollution(),    1e-9);
        assertEquals(40.0, original.getGroundPollution(), 1e-9);
        assertEquals(10.0, original.getWaterPollution(),  1e-9);
    }

    @Test
    void normalizeDoesNotChangeValidValues() {
        PollutionRegionData d = new PollutionRegionData(30.0, 40.0, 10.0, 25.0);
        d.normalize();
        assertEquals(30.0, d.getAirPollution(),    1e-9);
        assertEquals(40.0, d.getGroundPollution(), 1e-9);
        assertEquals(10.0, d.getWaterPollution(),  1e-9);
        assertEquals(25.0, d.getDecayResistance(), 1e-9);
    }
}
