package p.studio.compiler.specs;

import org.junit.jupiter.api.Test;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
import java.util.stream.Stream;

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

class NoModuleKeyRegressionSpecTest {
    private static final Pattern FORBIDDEN_IDENTIFIERS = Pattern.compile("\\bmoduleKey\\b|\\bcalleeModuleKey\\b");
    private static final List<String> STRUCTURAL_SOURCE_ROOTS = List.of(
            "prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/models",
            "prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/source/tables",
            "prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs",
            "prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/services",
            "prometeu-compiler/prometeu-build-pipeline/src/main/java/p/studio/compiler/backend/irvm");

    @Test
    void structuralContractsMustNotReintroduceLegacyModuleKeyIdentifiers() throws IOException {
        final var repoRoot = locateRepoRoot();
        final var violations = new ArrayList<String>();
        for (final var rootRelativePath : STRUCTURAL_SOURCE_ROOTS) {
            final var root = repoRoot.resolve(rootRelativePath);
            if (!Files.isDirectory(root)) {
                continue;
            }
            try (Stream<Path> files = Files.walk(root)) {
                files.filter(path -> Files.isRegularFile(path) && path.toString().endsWith(".java"))
                        .forEach(path -> recordViolation(path, repoRoot, violations));
            }
        }

        assertTrue(
                violations.isEmpty(),
                "legacy moduleKey identifier is forbidden in structural FE/BE contracts:\n" + String.join("\n", violations));
    }

    private void recordViolation(
            final Path path,
            final Path repoRoot,
            final ArrayList<String> violations) {
        final String content;
        try {
            content = Files.readString(path);
        } catch (IOException e) {
            throw new IllegalStateException("failed to read source file: " + path, e);
        }
        final var matcher = FORBIDDEN_IDENTIFIERS.matcher(content);
        if (matcher.find()) {
            final var relativePath = repoRoot.relativize(path).toString().replace('\\', '/');
            violations.add(relativePath + " (" + matcher.group() + ")");
        }
    }

    private Path locateRepoRoot() {
        var cursor = Path.of(System.getProperty("user.dir")).toAbsolutePath().normalize();
        while (cursor != null) {
            final var hasDocs = Files.isDirectory(cursor.resolve("docs/specs/compiler"));
            final var hasCompiler = Files.isDirectory(cursor.resolve("prometeu-compiler"));
            if (hasDocs && hasCompiler) {
                return cursor;
            }
            cursor = cursor.getParent();
        }
        fail("could not locate repository root from working directory");
        throw new IllegalStateException("unreachable");
    }
}
