import GenesisDivergenceReporter from "./GenesisDivergenceReporter.js";
import GenesisEquivalenceComparisonBasis from "./GenesisEquivalenceComparisonBasis.js";
import GenesisEquivalenceGateResult from "./GenesisEquivalenceGateResult.js";
import GenesisEquivalenceProof from "./GenesisEquivalenceProof.js";
import GenesisEquivalenceProofFailure from "./GenesisEquivalenceProofFailure.js";
import GenesisEquivalenceReading from "./GenesisEquivalenceReading.js";
import GraphModelMigrationNotice from "./GraphModelMigrationNotice.js";
import WarpError from "../errors/WarpError.js";
const MISSING_EQUIVALENCE_BOUNDARY_CODE = 'E_MISSING_EQUIVALENCE_BOUNDARY';
/** Gates scratch migration promotion on genesis replay equivalence. */
export default class GenesisEquivalenceGate {
    /** Compares legacy and scratch readings and returns promotion evidence. */
    evaluate(basis, legacyReading, scratchReading) {
        const checkedBasis = requireBasis(basis);
        const checkedLegacy = requireReading(legacyReading, 'legacyReading');
        const checkedScratch = requireReading(scratchReading, 'scratchReading');
        const proofResult = new GenesisEquivalenceProof().compare(checkedBasis, checkedLegacy, checkedScratch);
        const divergenceReport = proofResult instanceof GenesisEquivalenceProofFailure
            ? new GenesisDivergenceReporter().report(proofResult)
            : null;
        return new GenesisEquivalenceGateResult({
            proofResult,
            divergenceReport,
            fatalErrors: collectBoundaryFatalErrors(checkedLegacy, checkedScratch),
        });
    }
}
function collectBoundaryFatalErrors(legacyReading, scratchReading) {
    const missing = legacyReading.facts
        .concat(scratchReading.facts)
        .filter((fact) => fact.boundary === null);
    if (missing.length === 0) {
        return Object.freeze([]);
    }
    return Object.freeze([
        GraphModelMigrationNotice.fatal(MISSING_EQUIVALENCE_BOUNDARY_CODE, `genesis equivalence gate requires boundary evidence for ${missing.length} visible fact(s)`),
    ]);
}
function requireBasis(basis) {
    if (!(basis instanceof GenesisEquivalenceComparisonBasis)) {
        throw new WarpError('basis must be a GenesisEquivalenceComparisonBasis', 'E_VALIDATION');
    }
    return basis;
}
function requireReading(reading, label) {
    if (!(reading instanceof GenesisEquivalenceReading)) {
        throw new WarpError(`${label} must be a GenesisEquivalenceReading`, 'E_VALIDATION');
    }
    return reading;
}
