package com.codechecker.api.parser;

import com.codechecker.git.GitChangeScanner;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;

/**
 * 按简单类名在仓库中定位 .java 源文件。
 */
public class JavaSourceLocator {
    private final Path repoRoot;
    private final List<String> searchDirs;

    public JavaSourceLocator(Path repoRoot, List<String> searchDirs) {
        this.repoRoot = repoRoot;
        this.searchDirs = searchDirs;
    }

    public Optional<String> readSourceBySimpleName(String simpleClassName) throws IOException {
        Optional<Path> path = findFile(simpleClassName);
        if (path.isEmpty()) {
            return Optional.empty();
        }
        return Optional.of(Files.readString(path.get()));
    }

    public Optional<String> readSourceAtCommit(GitChangeScanner gitScanner, String sha,
                                               String simpleClassName) throws IOException {
        Optional<String> relativePath = findRelativePath(simpleClassName);
        if (relativePath.isEmpty()) {
            return Optional.empty();
        }
        String source = gitScanner.readFileAtCommit(sha, relativePath.get());
        if (source == null || source.isBlank()) {
            return Optional.empty();
        }
        return Optional.of(source);
    }

    public Optional<String> findRelativePath(String simpleClassName) throws IOException {
        Optional<Path> path = findFile(simpleClassName);
        return path.map(p -> repoRoot.relativize(p).toString().replace('\\', '/'));
    }

    public Optional<Path> findFile(String simpleClassName) throws IOException {
        String fileName = simpleClassName + ".java";
        for (String dir : searchDirs) {
            Path root = repoRoot.resolve(dir.replace('\\', '/'));
            if (!Files.exists(root)) {
                continue;
            }
            try (Stream<Path> walk = Files.walk(root)) {
                Optional<Path> found = walk
                        .filter(p -> p.getFileName().toString().equals(fileName))
                        .findFirst();
                if (found.isPresent()) {
                    return found;
                }
            }
        }
        return Optional.empty();
    }
}
