import { compareStrings } from "../utils/StringComparison.js";
import GenesisEquivalenceReadingFact from "./GenesisEquivalenceReadingFact.js";
import WarpError from "../errors/WarpError.js";
/** Runtime-backed observer-visible reading for genesis equivalence comparison. */
export default class GenesisEquivalenceReading {
    readingId;
    facts;
    constructor(fields) {
        const checkedFields = requireFields(fields);
        this.readingId = requireNonEmptyString(checkedFields.readingId, 'readingId');
        this.facts = freezeFacts(checkedFields.facts);
        Object.freeze(this);
    }
}
/** Validates the constructor envelope. */
function requireFields(fields) {
    if (fields === null || fields === undefined) {
        throw new WarpError('GenesisEquivalenceReading fields must be provided', 'E_VALIDATION');
    }
    return fields;
}
/** Validates and freezes visible facts in deterministic order. */
function freezeFacts(facts) {
    const checked = requireArray(facts, 'facts').map(requireFact);
    requireUniqueFactKeys(checked);
    return Object.freeze([...checked].sort(compareFacts));
}
/** Requires an array field. */
function requireArray(items, label) {
    if (items === null || items === undefined || !Array.isArray(items)) {
        throw new WarpError(`GenesisEquivalenceReading ${label} must be an array`, 'E_VALIDATION');
    }
    const checkedItems = items;
    return checkedItems;
}
/** Requires a visible fact instance. */
function requireFact(fact) {
    if (!(fact instanceof GenesisEquivalenceReadingFact)) {
        throw new WarpError('facts must contain GenesisEquivalenceReadingFact instances', 'E_VALIDATION');
    }
    return fact;
}
/** Requires unique visible fact keys. */
function requireUniqueFactKeys(facts) {
    const seen = new Set();
    for (const fact of facts) {
        const key = fact.toKey();
        if (seen.has(key)) {
            throw new WarpError(`GenesisEquivalenceReading duplicates visible fact ${key}`, 'E_VALIDATION');
        }
        seen.add(key);
    }
}
/** Compares visible facts deterministically. */
function compareFacts(left, right) {
    return compareStrings(left.toKey(), right.toKey());
}
/** Validates a required non-empty string. */
function requireNonEmptyString(value, name) {
    if (typeof value !== 'string' || value.length === 0) {
        throw new WarpError(`${name} must be a non-empty string`, 'E_VALIDATION');
    }
    return value;
}
