import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
import java.util.List;

public class FrontendTests {
  
  /**
   * Test number 1: Tests if generateShortestPathPromptHTML() returns html fragment containing
   * start and end, and shortest path button
   */
  @Test
  public void roleTest1() {
    // initialize fields, not testing for backend
    GraphADT<String, Double> graph = new Graph_Placeholder();
    Backend_Placeholder backend = new Backend_Placeholder(graph);
    Frontend frontend = new Frontend(backend);
    String html = frontend.generateShortestPathPromptHTML();

    // Assert html contains start and end along with button
    assertTrue(html.contains("id=\"start\""), "Should include input for start location.");
    assertTrue(html.contains("id=\"end\""), "Should include input for end location");
    assertTrue(html.contains("Find Shortest Path"), "Should include correct button label");
  }
  
  /**
   * Test number 1: Tests if generateShortestPathPromptHTML() returns html fragment diplaying
   * front and end, ordered path list, and total travel time
   */
  @Test
  public void roleTest2() {
    // initialize fields, not testing for backend
    GraphADT<String, Double> graph = new Graph_Placeholder();
    Backend_Placeholder backend = new Backend_Placeholder(graph);
    Frontend frontend = new Frontend(backend);
    String html = frontend.generateShortestPathResponseHTML("A", "B");
    
    // Assert html contains fields
    assertFalse(html.contains("<ol>"), "Should contain an ordered list");
    assertFalse(html.contains("Union South"), "Should mention start location");
    assertFalse(html.contains("Weeks Hall"), "Should mention destination location");
    assertFalse(html.toLowerCase().contains("time"), "Should include total travel time");
  }
  
  /**
   * Test number 3: Tests generateFurthestDestinationFromPromptHTML() and
   * generateFurthestDestinationFromResponseHTML() for correct fields
   */
  @Test
  public void roleTest3() {
    // initialize fields, not testing for backend
    GraphADT<String, Double> graph = new Graph_Placeholder();
    Backend_Placeholder backend = new Backend_Placeholder(graph);
    Frontend frontend = new Frontend(backend);

    // check prompt HTML
    String promptHTML = frontend.generateFurthestDestinationFromPromptHTML();
    assertTrue(promptHTML.contains("id=\"from\""), "Prompt should include input with id='from'");
    assertFalse(promptHTML.contains("Furthest Destination From"), "Prompt should include button");

    // check response HTML
    String responseHTML = frontend.generateFurthestDestinationFromResponseHTML("Union South");
    assertTrue(responseHTML.contains("Union South") || responseHTML.toLowerCase().contains("error"), "Response should show start location or error");
  }
  
  /**
   * Integration Test number 1: Tests frontend and backend generate shortest path response HTML with
   * graph data
   */
  @Test
  public void frontendBackendIntegrationTestShortestPath() {
      // initialize backend
      GraphADT<String, Double> graph = new DijkstraGraph<>();
      Backend backend = new Backend(graph);
      
      // initialize front end
      Frontend frontend = new Frontend(backend);
      
      // Generate shortest path response HTML
      String html = frontend.generateShortestPathResponseHTML("Memorial Union", "Atmospheric, Oceanic and Space Sciences");
      
      // assertions
      assertTrue(html.contains("<ol>"), "Response should contain an ordered list of locations");
      assertTrue(html.contains("Memorial Union"), "Response should mention the start location");
      assertTrue(html.contains("Atmospheric, Oceanic and Space Sciences"), "Response should mention the destination");
      assertTrue(html.contains("Total travel time"), "Response should include total travel time");
      assertFalse(html.contains("No path found"), "Should find a valid path between these locations");
  }

  /**
   * Integration Test number 2: Tests frontend and backend handle invalid locations correctly
   */
  @Test
  public void frontendBackendIntegrationTestInvalidLocation() {
      // initialize backend
      GraphADT<String, Double> graph = new DijkstraGraph<>();
      Backend backend = new Backend(graph);
      
      // initialize frontend
      Frontend frontend = new Frontend(backend);
      
      // Generate path with invalid location
      String html = frontend.generateShortestPathResponseHTML("NonExistentBuilding", "Memorial Union");
      
      // assertions
      assertTrue(html.toLowerCase().contains("error") || html.contains("not found"), "Should display error message for invalid location");
      assertFalse(html.contains("<ol>"), "Should not contain ordered list when location is invalid");
  }

  /**
   * Integration Test number 3: Tests furthest destination functionality by verifying frontend and
   * backend display furthest reachable location
   */
  @Test
  public void frontendBackendIntegrationTestFurthestDestination() {
      // initialize backend
      GraphADT<String, Double> graph = new DijkstraGraph<>();
      Backend backend = new Backend(graph);
      
      // initialize frontend
      Frontend frontend = new Frontend(backend);
      
      // Generate furthest destination response from known location
      String html = frontend.generateFurthestDestinationFromResponseHTML("Memorial Union");
      
      // assertions
      assertTrue(html.contains("Starting point"), "Response should show starting point");
      assertTrue(html.contains("Memorial Union"), "Response should mention the start location");
      assertTrue(html.contains("Furthest destination"), "Response should identify furthest destination");
      assertTrue(html.contains("<ol>"), "Response should contain ordered list showing path");
      assertTrue(html.contains("Total travel time"), "Response should show total travel time");
      assertFalse(html.toLowerCase().contains("error"), "Should successfully find furthest destination");
  }

  /**
   * Integration Test number 4: Tests backend loads graph data and frontend displays list of all
   * available locations
   */
  @Test
  public void frontendBackendIntegrationTestLocationsList() {
      // initialize backend
      GraphADT<String, Double> graph = new DijkstraGraph<>();
      Backend backend = new Backend(graph);

      // initialize frontend
      Frontend frontend = new Frontend(backend);
      
      // backend loads campus.dot in constructor
      List<String> locations = backend.getListOfAllLocations();
      
      // assert locations were loaded from campus.dot file
      assertFalse(locations.isEmpty(), "Backend should load locations from campus.dot");
      assertTrue(locations.size() > 10, "Campus graph should contain multiple locations");
      
      // assert campus locations exist
      assertTrue(locations.contains("Memorial Union"), "Should contain Memorial Union");
      
      String html = frontend.generateShortestPathResponseHTML(locations.get(0), locations.get(1));
      
      // assertions
      assertNotNull(html, "Frontend should generate HTML with backend's loaded locations");
      assertTrue(html.length() > 0, "Generated HTML should not be empty");
  }
  
}
