package com.livingworld.modules;

import com.livingworld.events.LivingWorldEvent;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * Immutable result returned by a module after updating a region.
 *
 * <p>This class prevents modules from mutating global systems directly during
 * update. Instead, they return results which SimulationManager applies in a
 * controlled way.</p>
 */
public final class ModuleUpdateResult {

    private final boolean changedRegion;
    private final List<LivingWorldEvent> generatedEvents;
    private final List<HistoryRecord> historyRecords;
    private final int estimatedCost;
    private final List<String> warnings;

    /**
     * Creates a new ModuleUpdateResult with the given values.
     *
     * @param changedRegion   whether this update modified the region
     * @param generatedEvents list of events generated during the update (null becomes empty list)
     * @param historyRecords  list of historical records to persist (null becomes empty list)
     * @param estimatedCost   estimated computational cost (must not be negative)
     * @param warnings        list of warning messages from this update (null becomes empty list)
     */
    public ModuleUpdateResult(boolean changedRegion, List<LivingWorldEvent> generatedEvents,
                              List<HistoryRecord> historyRecords, int estimatedCost, List<String> warnings) {

        if (estimatedCost < 0) {
            throw new IllegalArgumentException("estimatedCost must not be negative");
        }

        this.changedRegion = changedRegion;
        this.generatedEvents = generatedEvents != null ? Collections.unmodifiableList(new ArrayList<>(generatedEvents)) : Collections.emptyList();
        this.historyRecords = historyRecords != null ? Collections.unmodifiableList(new ArrayList<>(historyRecords)) : Collections.emptyList();
        this.estimatedCost = estimatedCost;
        this.warnings = warnings != null ? Collections.unmodifiableList(new ArrayList<>(warnings)) : Collections.emptyList();
    }

    /**
     * Returns a result indicating no changes were made to the region.
     */
    public static ModuleUpdateResult noChange() {
        return new ModuleUpdateResult(false, Collections.emptyList(), Collections.emptyList(), 0, Collections.emptyList());
    }

    /**
     * Returns a result indicating the region was changed.
     */
    public static ModuleUpdateResult changed() {
        return new ModuleUpdateResult(true, Collections.emptyList(), Collections.emptyList(), 0, Collections.emptyList());
    }

    /**
     * Returns whether this update modified the region.
     */
    public boolean changedRegion() {
        return changedRegion;
    }

    /**
     * Returns an unmodifiable list of events generated during the update.
     */
    public List<LivingWorldEvent> generatedEvents() {
        return generatedEvents;
    }

    /**
     * Returns an unmodifiable list of historical records to persist.
     */
    public List<HistoryRecord> historyRecords() {
        return historyRecords;
    }

    /**
     * Returns the estimated computational cost of this update.
     */
    public int estimatedCost() {
        return estimatedCost;
    }

    /**
     * Returns an unmodifiable list of warning messages from this update.
     */
    public List<String> warnings() {
        return warnings;
    }
}