package p.studio.compiler.integration;

import org.junit.jupiter.api.Test;
import p.studio.compiler.messages.BuilderPipelineConfig;
import p.studio.compiler.workspaces.BuilderPipelineService;
import p.studio.utilities.logs.LogAggregator;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;

import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;

class MainProjectPipelineIntegrationTest {

    @Test
    void shouldCompileMainProjectAndWriteProgramBytecode() throws IOException {
        final var repoRoot = findRepoRoot(Path.of("").toAbsolutePath().normalize());
        final var projectRoot = repoRoot.resolve("test-projects").resolve("main");
        final var outputPath = projectRoot.resolve("build").resolve("program.pbx");
        Files.createDirectories(outputPath.getParent());
        Files.deleteIfExists(outputPath);

        final var logsOut = new StringBuilder();
        final var logs = LogAggregator.with(line -> {
            logsOut.append(line);
            if (!line.endsWith("\n")) {
                logsOut.append('\n');
            }
        });

        assertDoesNotThrow(
                () -> BuilderPipelineService.INSTANCE.run(new BuilderPipelineConfig(false, projectRoot.toString()), logs),
                logsOut::toString);
        assertTrue(Files.exists(outputPath), "pipeline did not write output: " + outputPath + "\n" + logsOut);
        assertTrue(Files.size(outputPath) > 0, "pipeline wrote empty bytecode file: " + outputPath + "\n" + logsOut);
    }

    private Path findRepoRoot(final Path start) {
        var current = start;
        while (current != null) {
            if (Files.exists(current.resolve("settings.gradle.kts"))
                    && Files.exists(current.resolve("test-projects").resolve("main").resolve("prometeu.json"))) {
                return current;
            }
            current = current.getParent();
        }
        fail("unable to locate repository root from " + start);
        return start;
    }
}
