package com.livingworld.regions.query;

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

import java.util.List;

import org.junit.jupiter.api.Test;

import com.livingworld.regions.Region;
import com.livingworld.regions.RegionCoordinate;
import com.livingworld.regions.RegionFactory;
import com.livingworld.regions.cache.RegionCache;

class RegionQueryEngineTest {

    private final RegionFactory factory = new RegionFactory();
    private final RegionCache cache = new RegionCache();
    private final RegionQueryEngine queries = new RegionQueryEngine(cache);

    @Test
    void radiusQueryUsesRegionCoordinatesAndCurrentDimension() {
        Region center = add("minecraft:overworld", 0, 0);
        add("minecraft:overworld", 1, 1);
        add("minecraft:overworld", 2, 0);
        add("minecraft:the_nether", 0, 0);

        assertEquals(
                List.of(center.getCoordinate(), new RegionCoordinate("minecraft:overworld", 1, 1)),
                queries.getRegionsInRadius(center.getCoordinate(), 1).stream()
                        .map(Region::getCoordinate)
                        .toList());
    }

    @Test
    void ecosystemQueriesUseFlagsAndMetrics() {
        Region affected = add("minecraft:overworld", 0, 0);
        affected.getFlags().setHasActiveEcosystemEvent(true);
        affected.getMetrics().setPollutionScore(80);
        affected.getMetrics().setSoilQuality(20);

        Region healthy = add("minecraft:overworld", 1, 0);
        healthy.getMetrics().setPollutionScore(10);
        healthy.getMetrics().setSoilQuality(80);

        assertEquals(List.of(affected), queries.getRegionsWithActiveEcosystemEvent());
        assertEquals(List.of(affected), queries.getRegionsAbovePollution(50));
        assertEquals(List.of(affected), queries.getRegionsBelowSoilQuality(50));
    }

    @Test
    void validatesArguments() {
        assertThrows(IllegalArgumentException.class,
                () -> new RegionQueryEngine(null));
        assertThrows(IllegalArgumentException.class,
                () -> queries.getRegion(null));
        assertThrows(IllegalArgumentException.class,
                () -> queries.getRegionsInRadius(new RegionCoordinate("minecraft:overworld", 0, 0), -1));
        assertThrows(IllegalArgumentException.class,
                () -> queries.getRegionsAbovePollution(Double.NaN));
        assertThrows(IllegalArgumentException.class,
                () -> queries.getRegionsBelowSoilQuality(101));
    }

    private Region add(String dimensionId, int x, int z) {
        Region region = factory.createNewRegion(new RegionCoordinate(dimensionId, x, z), 0);
        cache.put(region);
        return region;
    }
}
