package p.studio.compiler.workspaces.phases;

import p.studio.compiler.messages.BuildingIssueSink;
import p.studio.compiler.models.DependencyContext;
import p.studio.compiler.workspaces.DependencyPhase;

public final class ValidatePhase implements DependencyPhase {
    @Override
    public BuildingIssueSink run(final DependencyContext ctx) {
        // ensure rootProjectId is set
        if (ctx.rootProjectId == null) {
            return BuildingIssueSink.empty()
                    .report(builder -> builder
                        .error(true)
                        .message("[DEPS]: rootProjectId ProjectId not set"));
        }
        if (ctx.rootStdlib == null) {
            return BuildingIssueSink.empty()
                    .report(builder -> builder
                        .error(true)
                        .message("[DEPS]: root stdlib major not set"));
        }

        // ensure the dependenciesByProject matches the number of projectDescriptors
        if (ctx.dependenciesByProject.size() != ctx.projectTable.size()) {
            return BuildingIssueSink.empty()
                    .report(builder -> builder
                        .error(true)
                        .message("[DEPS]: internal error: dependenciesByProject and projectDescriptors size mismatch"));
        }

        final BuildingIssueSink depIssues = BuildingIssueSink.empty();

        // ensure compatibility across stdlibs
        for (final var projectInfo : ctx.projectInfoTable.values()) {
            if (projectInfo.manifest.stdlib() > ctx.rootStdlib) {
                depIssues.report(builder -> builder
                    .error(true)
                    .message(String.format(
                            "[DEPS]: incompatible stdlib: [%s] requires stdlib \"%d\" but root project uses stdlib \"%d\"",
                            projectInfo.manifest.name(),
                            projectInfo.manifest.stdlib(),
                            ctx.rootStdlib)));
            }
        }

        // ensure uniformity to version across the same projectIds (associated by name)
        for (final var entry : ctx.projectNameAndVersions.entrySet()) {
            final var name = entry.getKey();
            final var versions = entry.getValue();
            if (versions.size() > 1) {
                depIssues.report(builder -> builder
                    .error(true)
                    .message("[DEPS]: inconsistent version for project: " + name + " (" + versions + ")"));
            }
        }

        if (!depIssues.isEmpty()) {
            return depIssues;
        }

        // run check over source policy (if any) from here (FrontedSpec)

        return BuildingIssueSink.empty();
    }
}
