import GitWarpSuffixTransformHologram from "./GitWarpSuffixTransformHologram.js";
import GitWarpWitnessedSuffixAdmissionOutcome from "./GitWarpWitnessedSuffixAdmissionOutcome.js";
import GitWarpWitnessedSuffixSourceFacts from "./GitWarpWitnessedSuffixSourceFacts.js";
import WarpError from "../errors/WarpError.js";
/** Observer-readable shell for importing a witnessed git-warp suffix. */
export default class GitWarpWitnessedSuffixAdmissionShell {
    graphName;
    laneId;
    transportedSiteRef;
    sourceFrontierRef;
    basisFrontierRef;
    targetFrontierRef;
    admissionLawId;
    transportLawId;
    outcome;
    sourceFacts;
    hologram;
    patchRefs;
    patchCount;
    witnessRef;
    bundleDigest;
    proofRef;
    constructor(fields) {
        const checkedFields = requireFields(fields);
        const sourceFacts = requireSourceFacts(checkedFields.sourceFacts);
        const hologram = requireHologram(checkedFields.hologram);
        requireMatchingFrontiers(sourceFacts, hologram);
        requireMatchingPatchCount(sourceFacts, hologram);
        this.graphName = sourceFacts.graphName;
        this.laneId = requireNonEmptyString(checkedFields.laneId, 'laneId');
        this.transportedSiteRef = requireNonEmptyString(checkedFields.transportedSiteRef, 'transportedSiteRef');
        this.sourceFrontierRef = sourceFacts.sourceFrontierRef;
        this.basisFrontierRef = sourceFacts.basisFrontierRef;
        this.targetFrontierRef = sourceFacts.targetFrontierRef;
        this.admissionLawId = requireNonEmptyString(checkedFields.admissionLawId, 'admissionLawId');
        this.transportLawId = hologram.transportLawId;
        this.outcome = requireOutcome(checkedFields.outcome);
        this.sourceFacts = sourceFacts;
        this.hologram = hologram;
        this.patchRefs = freezePatchRefs(sourceFacts);
        this.patchCount = sourceFacts.patchCount;
        this.witnessRef = sourceFacts.witnessRef;
        this.bundleDigest = sourceFacts.bundleDigest;
        this.proofRef = hologram.proofRef;
        Object.freeze(this);
    }
    /** Deterministically materializes the admitted target state from a comparable basis. */
    materializeFrom(basis) {
        return this.hologram.materializeFrom(basis);
    }
    /** Returns true until runtime-boundary has a generated Wesley profile and fixture. */
    requiresGeneratedProfileBeforeProjection() {
        return this.sourceFacts.requiresGeneratedProfileBeforeProjection();
    }
    isAdmitted() {
        return this.outcome.isAdmitted();
    }
    requiresResolution() {
        return this.outcome.requiresResolution();
    }
}
function requireFields(value) {
    if (value === null || value === undefined) {
        throw new WarpError('GitWarpWitnessedSuffixAdmissionShell fields must be provided', 'E_VALIDATION');
    }
    return value;
}
function requireSourceFacts(value) {
    if (!(value instanceof GitWarpWitnessedSuffixSourceFacts)) {
        throw new WarpError('sourceFacts must be GitWarpWitnessedSuffixSourceFacts', 'E_VALIDATION');
    }
    return value;
}
function requireHologram(value) {
    if (!(value instanceof GitWarpSuffixTransformHologram)) {
        throw new WarpError('hologram must be GitWarpSuffixTransformHologram', 'E_VALIDATION');
    }
    return value;
}
function requireOutcome(value) {
    if (!(value instanceof GitWarpWitnessedSuffixAdmissionOutcome)) {
        throw new WarpError('outcome must be GitWarpWitnessedSuffixAdmissionOutcome', 'E_VALIDATION');
    }
    return value;
}
function requireMatchingFrontiers(sourceFacts, hologram) {
    requireSameValue(sourceFacts.sourceFrontierRef, hologram.sourceFrontierRef, 'sourceFrontierRef');
    requireSameValue(sourceFacts.basisFrontierRef, hologram.basisFrontierRef, 'basisFrontierRef');
    requireSameValue(sourceFacts.targetFrontierRef, hologram.targetFrontierRef, 'targetFrontierRef');
}
function requireMatchingPatchCount(sourceFacts, hologram) {
    if (sourceFacts.patchCount !== hologram.patchCount) {
        throw new WarpError('source facts and suffix hologram must name the same patch count', 'E_VALIDATION');
    }
}
function requireSameValue(left, right, name) {
    if (left !== right) {
        throw new WarpError(`source facts and suffix hologram ${name} must match`, 'E_VALIDATION');
    }
}
function freezePatchRefs(sourceFacts) {
    return Object.freeze(sourceFacts.patches.map((patch) => patch.patchSha));
}
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;
}
