/**
 * GCPolicy — garbage collection thresholds for the current WARP state.
 *
 * Instances are immutable value objects. `evaluate()` checks a set of
 * runtime metrics against the thresholds and returns a frozen
 * `GCShouldRunResult` naming every threshold that was exceeded.
 *
 * @module domain/services/GCPolicy
 */
import GCShouldRunResult from "./GCShouldRunResult.js";
const DEFAULT_TOMBSTONE_RATIO_THRESHOLD = 0.3;
const DEFAULT_ENTRY_COUNT_THRESHOLD = 50_000;
const DEFAULT_MIN_PATCHES_SINCE_COMPACTION = 1_000;
const DEFAULT_MAX_TICKS_SINCE_COMPACTION = 10_000;
export default class GCPolicy {
    /** When false, automatic GC is disabled even if thresholds are met. */
    enabled;
    /** Tombstone ratio (0..1) that triggers GC. */
    tombstoneRatioThreshold;
    /** Total entry count that triggers GC. */
    entryCountThreshold;
    /** Minimum patches between GCs. */
    minPatchesSinceCompaction;
    /** Maximum lamport ticks between GCs. */
    maxTicksSinceCompaction;
    /** Whether to auto-compact on checkpoint. */
    compactOnCheckpoint;
    constructor(fields) {
        this.enabled = fields.enabled;
        this.tombstoneRatioThreshold = fields.tombstoneRatioThreshold;
        this.entryCountThreshold = fields.entryCountThreshold;
        this.minPatchesSinceCompaction = fields.minPatchesSinceCompaction;
        this.maxTicksSinceCompaction = fields.maxTicksSinceCompaction;
        this.compactOnCheckpoint = fields.compactOnCheckpoint;
        Object.freeze(this);
    }
    /** Default policy — conservative, GC disabled by default (opt-in). */
    static DEFAULT = new GCPolicy({
        enabled: false,
        tombstoneRatioThreshold: DEFAULT_TOMBSTONE_RATIO_THRESHOLD,
        entryCountThreshold: DEFAULT_ENTRY_COUNT_THRESHOLD,
        minPatchesSinceCompaction: DEFAULT_MIN_PATCHES_SINCE_COMPACTION,
        maxTicksSinceCompaction: DEFAULT_MAX_TICKS_SINCE_COMPACTION,
        compactOnCheckpoint: true,
    });
    /**
     * Evaluates runtime metrics against this policy's thresholds.
     * Returns a `GCShouldRunResult` naming every threshold exceeded;
     * `shouldRun` is true iff any threshold tripped.
     */
    evaluate(input) {
        const reasons = [];
        if (input.tombstoneRatio > this.tombstoneRatioThreshold) {
            reasons.push(`Tombstone ratio ${(input.tombstoneRatio * 100).toFixed(1)}% ` +
                `exceeds threshold ${(this.tombstoneRatioThreshold * 100).toFixed(1)}%`);
        }
        if (input.totalEntries > this.entryCountThreshold) {
            reasons.push(`Entry count ${input.totalEntries} exceeds threshold ${this.entryCountThreshold}`);
        }
        if (input.patchesSinceCompaction > this.minPatchesSinceCompaction) {
            reasons.push(`Patches since compaction ${input.patchesSinceCompaction} ` +
                `exceeds minimum ${this.minPatchesSinceCompaction}`);
        }
        if (input.ticksSinceCompaction > this.maxTicksSinceCompaction) {
            reasons.push(`Ticks since compaction ${input.ticksSinceCompaction} ` +
                `exceeds maximum ${this.maxTicksSinceCompaction}`);
        }
        return new GCShouldRunResult(reasons);
    }
}
