package com.livingworld.debug;

import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.StringJoiner;

/**
 * Immutable snapshot of one simulation profiling cycle.
 */
public record SimulationProfileSnapshot(
        long totalCycleNanos,
        Map<String, Long> moduleTimings,
        int eventsPublished,
        int regionsUpdated,
        int savesPerformed,
        boolean budgetExceeded) {

    public SimulationProfileSnapshot {
        if (totalCycleNanos < 0) {
            throw new IllegalArgumentException("totalCycleNanos must not be negative");
        }
        if (moduleTimings == null) {
            throw new IllegalArgumentException("moduleTimings must not be null");
        }
        if (eventsPublished < 0 || regionsUpdated < 0 || savesPerformed < 0) {
            throw new IllegalArgumentException("profile counts must not be negative");
        }
        LinkedHashMap<String, Long> timingCopy = new LinkedHashMap<>();
        moduleTimings.forEach((moduleId, timingNanos) -> {
            if (moduleId == null || moduleId.isBlank()) {
                throw new IllegalArgumentException("Module IDs must not be blank");
            }
            if (timingNanos == null || timingNanos < 0) {
                throw new IllegalArgumentException("Module timings must be non-negative");
            }
            timingCopy.put(moduleId, timingNanos);
        });
        moduleTimings = Collections.unmodifiableMap(timingCopy);
    }

    public String toHumanReadableString() {
        StringJoiner formattedTimings = new StringJoiner(", ", "{", "}");
        moduleTimings.forEach((moduleId, timingNanos) ->
                formattedTimings.add(moduleId + "=" + timingNanos / 1_000_000.0 + "ms"));

        return "cycle=" + (totalCycleNanos / 1_000_000.0) + "ms"
                + ", modules=" + formattedTimings
                + ", events=" + eventsPublished
                + ", regions=" + regionsUpdated
                + ", saves=" + savesPerformed
                + ", budgetExceeded=" + budgetExceeded;
    }
}
