package com.graphtest;

import com.graphtest.model.NodeStatus;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.net.URL;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;

import static org.assertj.core.api.Assertions.*;

@DisplayName("Case 3: Circular Import (A → B → A)")
class Case3_CircularImportTest {

    private CodeGraph graph;

    @BeforeEach
    void setUp() throws Exception {
        URL resource = getClass().getClassLoader().getResource("fixtures/case3_circular");
        Path dir = Paths.get(resource.toURI());
        graph = new GraphBuilder().buildFromDirectory(dir);
    }

    @Test
    @DisplayName("Graph phải build thành công, không bị crash hoặc infinite loop")
    void graphShouldBuildWithoutCrash() {
        assertThat(graph).isNotNull();
        assertThat(graph.getNodes()).isNotEmpty();
    }

    @Test
    @DisplayName("Cả ClassA và ClassB phải tồn tại trong graph")
    void bothNodesShouldExist() {
        assertThat(graph.hasNode("ClassA")).isTrue();
        assertThat(graph.hasNode("ClassB")).isTrue();
    }

    @Test
    @DisplayName("Cả hai node đều có status OK")
    void bothNodesShouldHaveOkStatus() {
        assertThat(graph.getNode("ClassA").getStatus()).isEqualTo(NodeStatus.OK);
        assertThat(graph.getNode("ClassB").getStatus()).isEqualTo(NodeStatus.OK);
    }

    @Test
    @DisplayName("Edge ClassA → ClassB phải tồn tại")
    void edgeAToB_ShouldExist() {
        assertThat(graph.hasEdge("ClassA", "ClassB")).isTrue();
    }

    @Test
    @DisplayName("Edge ClassB → ClassA phải tồn tại")
    void edgeBToA_ShouldExist() {
        assertThat(graph.hasEdge("ClassB", "ClassA")).isTrue();
    }

    @Test
    @DisplayName("Cycle phải được phát hiện")
    void cycleShouldBeDetected() {
        assertThat(graph.getDetectedCycles()).isNotEmpty();
    }

    @Test
    @DisplayName("Cycle phải chứa cả ClassA và ClassB")
    void cycleShouldContainBothClasses() {
        List<List<String>> cycles = graph.getDetectedCycles();
        boolean cycleContainsBoth = cycles.stream().anyMatch(cycle ->
            cycle.contains("ClassA") && cycle.contains("ClassB"));
        assertThat(cycleContainsBoth).isTrue();
    }

    @Test
    @DisplayName("Circular import không gây build error")
    void circularImportShouldNotCauseBuildError() {
        assertThat(graph.getBuildErrors()).isEmpty();
    }
}
