import { compareStrings } from "../utils/StringComparison.js";
import GenesisEquivalenceComparisonBasis from "./GenesisEquivalenceComparisonBasis.js";
import GenesisEquivalenceMismatch from "./GenesisEquivalenceMismatch.js";
import GenesisEquivalenceProofSummary from "./GenesisEquivalenceProofSummary.js";
import WarpError from "../errors/WarpError.js";
/** Runtime-backed failed genesis replay equivalence result. */
export default class GenesisEquivalenceProofFailure {
    basis;
    summary;
    mismatches;
    constructor(fields) {
        const checkedFields = requireFields(fields);
        this.basis = requireBasis(checkedFields.basis);
        this.summary = requireSummary(checkedFields.summary);
        this.mismatches = freezeMismatches(checkedFields.mismatches);
        requireSummaryMatchesFailure(this.basis, this.summary, this.mismatches);
        Object.freeze(this);
    }
}
/** Validates the constructor envelope. */
function requireFields(fields) {
    if (fields === null || fields === undefined) {
        throw new WarpError('GenesisEquivalenceProofFailure fields must be provided', 'E_VALIDATION');
    }
    return fields;
}
/** Requires a comparison basis instance. */
function requireBasis(basis) {
    if (!(basis instanceof GenesisEquivalenceComparisonBasis)) {
        throw new WarpError('basis must be a GenesisEquivalenceComparisonBasis', 'E_VALIDATION');
    }
    return basis;
}
/** Requires a proof summary instance. */
function requireSummary(summary) {
    if (!(summary instanceof GenesisEquivalenceProofSummary)) {
        throw new WarpError('summary must be a GenesisEquivalenceProofSummary', 'E_VALIDATION');
    }
    return summary;
}
/** Validates and freezes mismatches in deterministic order. */
function freezeMismatches(mismatches) {
    const checked = requireArray(mismatches, 'mismatches').map(requireMismatch);
    if (checked.length === 0) {
        throw new WarpError('failed proof results must contain mismatches', 'E_VALIDATION');
    }
    return Object.freeze([...checked].sort(compareMismatches));
}
/** Requires an array field. */
function requireArray(items, label) {
    if (items === null || items === undefined || !Array.isArray(items)) {
        throw new WarpError(`GenesisEquivalenceProofFailure ${label} must be an array`, 'E_VALIDATION');
    }
    const checkedItems = items;
    return checkedItems;
}
/** Requires a mismatch instance. */
function requireMismatch(mismatch) {
    if (!(mismatch instanceof GenesisEquivalenceMismatch)) {
        throw new WarpError('mismatches must contain GenesisEquivalenceMismatch instances', 'E_VALIDATION');
    }
    return mismatch;
}
/** Requires summary and failure evidence to agree. */
function requireSummaryMatchesFailure(basis, summary, mismatches) {
    if (summary.basis.toKey() !== basis.toKey()) {
        throw new WarpError('summary basis must match failure basis', 'E_VALIDATION');
    }
    if (summary.mismatchCount !== mismatches.length) {
        throw new WarpError('failure summary mismatch count must match mismatches', 'E_VALIDATION');
    }
}
/** Compares mismatches deterministically. */
function compareMismatches(left, right) {
    return compareStrings(left.toKey(), right.toKey());
}
