///////////////////////////////////////////
///
/// File: BackendTests.java
/// Author: Evan Gaul
/// Email: eagaul@wisc.edu
/// Date: 11/5/25
/// Assignment: P209.RoleCode
/// Course: CS400 Lec004 Fall 2025
/// Professor: Ashley Samuelson
///
///////////////////////////////////////////
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.util.List;
import java.util.NoSuchElementException;

/**
 * JUnit tests for Backend.java
 */
public class BackendTests {

    private Backend backend;

    @BeforeEach
    public void setUp() throws IOException {
        // Use the placeholder graph for testing
        backend = new Backend(new Graph_Placeholder());
        // Load data from DOT file (or placeholder just has its own little path)
        backend.loadGraphData("campus.dot");
    }

    /**
     * roleTest1
     * Test getListOfAllLocations and findLocationsOnShortestPath
     */
    @Test
    public void roleTest1() {
        List<String> allLocations = backend.getListOfAllLocations();
        assertTrue(allLocations.size() >= 3, "Should have at least 3 nodes in the graph");

        List<String> path = backend.findLocationsOnShortestPath("Union South", "Weeks Hall for Geological Sciences");
        assertNotNull(path, "Shortest path should not be null");
        assertTrue(path.size() >= 2, "Path should contain at least start and end nodes");
    }

    /**
     * roleTest2
     * Test findTimesOnShortestPath and ensure times match path edges
     */
    @Test
    public void roleTest2() {
        List<Double> times = backend.findTimesOnShortestPath("Union South", "Weeks Hall for Geological Sciences");
        assertNotNull(times, "Times list should not be null");
        // There should be one less time than nodes in path
        List<String> path = backend.findLocationsOnShortestPath("Union South", "Weeks Hall for Geological Sciences");
        assertEquals(path.size() - 1, times.size(), "Times should match number of edges in path");

        // Test empty path returns empty times
        List<Double> emptyTimes = backend.findTimesOnShortestPath("This node dont exist", "Weeks Hall for Geological Sciences");
        assertTrue(emptyTimes.isEmpty(), "Times should be empty for invalid start node");
    }

    /**
     * roleTest3
     * Test getTenClosestDestinations
     */
    @Test
    public void roleTest3() {
        try {
            List<String> closest = backend.getTenClosestDestinations("Union South");
            assertNotNull(closest, "Closest destinations should not be null");
            assertTrue(closest.size() <= 10, "Should return at most 10 destinations");
            assertFalse(closest.contains("Union South"), "Start location should not be included");
        } catch (NoSuchElementException e) {
            fail("NoSuchElementException thrown unexpectedly");
        }

        // Test exception for node that does not exist
        assertThrows(NoSuchElementException.class, () -> {
            backend.getTenClosestDestinations("Fake Node");
        });
    }
}
