"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.REQUIRED_RELEASE_CANDIDATE_VERSION = exports.REQUIRED_RECONCILIATION_IDS = exports.REQUIRED_SOURCE_CRITERION_IDS = void 0;
exports.validateReleaseCandidateAdmission = validateReleaseCandidateAdmission;
exports.assertReleaseCandidateAdmitted = assertReleaseCandidateAdmitted;
exports.createReleaseCandidateAdmissionFixture = createReleaseCandidateAdmissionFixture;
exports.REQUIRED_SOURCE_CRITERION_IDS = Object.freeze(Array.from({ length: 38 }, (_, index) => `SRC-${String(index + 1).padStart(2, "0")}`));
exports.REQUIRED_RECONCILIATION_IDS = Object.freeze(Array.from({ length: 18 }, (_, index) => `REC-${String(index + 1).padStart(2, "0")}`));
exports.REQUIRED_RELEASE_CANDIDATE_VERSION = "0.1.23";
const NON_NEGATIVE_COUNT_FIELDS = Object.freeze([
    "deferredCount",
    "discoveredCount",
    "backlogCount",
    "residualCount",
    "followUpCount"
]);
function validateReleaseCandidateAdmission(input) {
    const findings = [];
    const add = (code, message, subjectId = null) => {
        findings.push(Object.freeze({ code, message, subjectId }));
    };
    if (input.cycleId.trim().length === 0) {
        add("CYCLE_ID_MISSING", "Admission evidence must identify its current cycle.");
    }
    validateCriteria(input.criteria, add);
    validateReconciliations(input.reconciliations, add);
    validateDeferredLanes(input.deferredLanes, add);
    validateCandidates(input.candidates, add);
    validatePublicationRecords(input.publicationRecords, add);
    validateBoundaries(input.boundaries, input.candidates, add);
    return Object.freeze({
        verdict: findings.length === 0 ? "admitted" : "rejected",
        findings: Object.freeze(findings),
        criterionCount: input.criteria.length,
        reconciliationCount: input.reconciliations.length,
        candidateCount: input.candidates.length,
        deferredLaneCount: input.deferredLanes.length,
        publicationCount: input.publicationRecords.length,
        boundaryCount: input.boundaries.length
    });
}
function assertReleaseCandidateAdmitted(input) {
    const result = validateReleaseCandidateAdmission(input);
    if (result.verdict === "rejected") {
        throw new Error(`Release candidate admission rejected: ${result.findings.map((finding) => finding.code).join(", ")}`);
    }
}
function createReleaseCandidateAdmissionFixture() {
    const criteria = exports.REQUIRED_SOURCE_CRITERION_IDS.map((criterionId) => Object.freeze({
        criterionId,
        evidenceId: `evidence:${criterionId}`,
        ownerId: `owner:${criterionId}`,
        status: "passing",
        strength: "strong",
        current: true
    }));
    const reconciliations = exports.REQUIRED_RECONCILIATION_IDS.map((reconciliationId) => Object.freeze({
        reconciliationId,
        evidenceId: `evidence:${reconciliationId}`,
        status: "completed",
        review: "accepted",
        current: true,
        deferredCount: 0,
        discoveredCount: 0,
        backlogCount: 0,
        residualCount: 0,
        followUpCount: 0
    }));
    return Object.freeze({
        cycleId: "phase05-release-admission",
        criteria: Object.freeze(criteria),
        reconciliations: Object.freeze(reconciliations),
        candidates: Object.freeze([
            Object.freeze({
                candidateId: "local-candidate-0.1.23",
                version: exports.REQUIRED_RELEASE_CANDIDATE_VERSION,
                qualificationVerdict: "qualified",
                qualificationEvidenceId: "phase05-milestone03-runtime-qualification",
                qualificationCurrent: true
            })
        ]),
        deferredLanes: Object.freeze([]),
        publicationRecords: Object.freeze([]),
        boundaries: Object.freeze([
            Object.freeze({
                boundaryId: "complete-correction-0.1.23",
                candidateId: "local-candidate-0.1.23",
                version: exports.REQUIRED_RELEASE_CANDIDATE_VERSION,
                state: "staged",
                scope: "complete-correction",
                published: false
            })
        ])
    });
}
function validateCriteria(criteria, add) {
    if (criteria.length !== exports.REQUIRED_SOURCE_CRITERION_IDS.length) {
        add("CRITERION_COUNT_MISMATCH", `Admission requires exactly ${exports.REQUIRED_SOURCE_CRITERION_IDS.length} source criteria.`);
    }
    const ids = criteria.map((criterion) => criterion.criterionId);
    if (new Set(ids).size !== ids.length) {
        add("CRITERION_ID_DUPLICATE", "Source criterion identities must be unique.");
    }
    const expectedSet = new Set(exports.REQUIRED_SOURCE_CRITERION_IDS);
    for (const id of ids) {
        if (!expectedSet.has(id)) {
            add("CRITERION_ID_UNEXPECTED", `Unexpected source criterion identity ${id}.`, id);
        }
    }
    for (const id of exports.REQUIRED_SOURCE_CRITERION_IDS) {
        if (!ids.includes(id)) {
            add("CRITERION_ID_MISSING", `Required source criterion identity ${id} is missing.`, id);
        }
    }
    if (criteria.length === exports.REQUIRED_SOURCE_CRITERION_IDS.length &&
        ids.some((id, index) => id !== exports.REQUIRED_SOURCE_CRITERION_IDS[index])) {
        add("CRITERION_ORDER_MISMATCH", "Source criteria must retain authoritative source order.");
    }
    for (const criterion of criteria) {
        if (criterion.evidenceId.trim().length === 0) {
            add("CRITERION_EVIDENCE_MISSING", "Criterion evidence identity is required.", criterion.criterionId);
        }
        if (criterion.ownerId.trim().length === 0) {
            add("CRITERION_OWNER_MISSING", "Criterion evidence ownership is required.", criterion.criterionId);
        }
        if (criterion.status !== "passing") {
            add("CRITERION_NOT_PASSING", "Every source criterion must have passing evidence.", criterion.criterionId);
        }
        if (criterion.strength !== "strong") {
            add("CRITERION_EVIDENCE_WEAK", "Every source criterion must have strong evidence.", criterion.criterionId);
        }
        if (!criterion.current) {
            add("CRITERION_EVIDENCE_STALE", "Every source criterion must have current-cycle evidence.", criterion.criterionId);
        }
    }
}
function validateReconciliations(reconciliations, add) {
    if (reconciliations.length !== exports.REQUIRED_RECONCILIATION_IDS.length) {
        add("RECONCILIATION_COUNT_MISMATCH", `Admission requires exactly ${exports.REQUIRED_RECONCILIATION_IDS.length} reconciliations.`);
    }
    const ids = reconciliations.map((reconciliation) => reconciliation.reconciliationId);
    if (new Set(ids).size !== ids.length) {
        add("RECONCILIATION_ID_DUPLICATE", "Reconciliation identities must be unique.");
    }
    const expectedSet = new Set(exports.REQUIRED_RECONCILIATION_IDS);
    for (const id of ids) {
        if (!expectedSet.has(id)) {
            add("RECONCILIATION_ID_UNEXPECTED", `Unexpected reconciliation identity ${id}.`, id);
        }
    }
    for (const id of exports.REQUIRED_RECONCILIATION_IDS) {
        if (!ids.includes(id)) {
            add("RECONCILIATION_ID_MISSING", `Required reconciliation identity ${id} is missing.`, id);
        }
    }
    if (reconciliations.length === exports.REQUIRED_RECONCILIATION_IDS.length &&
        ids.some((id, index) => id !== exports.REQUIRED_RECONCILIATION_IDS[index])) {
        add("RECONCILIATION_ORDER_MISMATCH", "Reconciliations must retain declared correction order.");
    }
    for (const reconciliation of reconciliations) {
        const id = reconciliation.reconciliationId;
        if (reconciliation.evidenceId.trim().length === 0) {
            add("RECONCILIATION_EVIDENCE_MISSING", "Reconciliation evidence identity is required.", id);
        }
        if (reconciliation.status !== "completed") {
            add("RECONCILIATION_INCOMPLETE", "Every required reconciliation must be completed.", id);
        }
        if (reconciliation.review !== "accepted") {
            add("RECONCILIATION_NOT_ACCEPTED", "Every required reconciliation must be accepted.", id);
        }
        if (!reconciliation.current) {
            add("RECONCILIATION_EVIDENCE_STALE", "Every reconciliation must be current for admission.", id);
        }
        for (const field of NON_NEGATIVE_COUNT_FIELDS) {
            const value = reconciliation[field];
            if (!Number.isSafeInteger(value) || value < 0) {
                add("RECONCILIATION_COUNT_INVALID", `${field} must be a non-negative safe integer.`, id);
            }
            else if (value !== 0) {
                add("RECONCILIATION_OPEN_WORK", `${field} must be zero before admission.`, id);
            }
        }
    }
}
function validateDeferredLanes(deferredLanes, add) {
    if (deferredLanes.length > 0) {
        add("DEFERRED_LANES_PRESENT", "Admission requires zero deferred corrective lanes.");
    }
    for (const lane of deferredLanes) {
        if (lane.trim().length === 0) {
            add("DEFERRED_LANE_ID_MISSING", "Deferred lane identities must be non-empty.");
        }
    }
}
function validateCandidates(candidates, add) {
    if (candidates.length !== 1) {
        add("CANDIDATE_COUNT_MISMATCH", "Admission requires exactly one release candidate.");
    }
    for (const candidate of candidates) {
        if (candidate.candidateId.trim().length === 0) {
            add("CANDIDATE_ID_MISSING", "Candidate identity is required.");
        }
        if (candidate.version !== exports.REQUIRED_RELEASE_CANDIDATE_VERSION) {
            add("CANDIDATE_VERSION_MISMATCH", `Admission requires candidate version ${exports.REQUIRED_RELEASE_CANDIDATE_VERSION}.`, candidate.candidateId);
        }
        if (candidate.qualificationVerdict !== "qualified") {
            add("CANDIDATE_NOT_QUALIFIED", "The release candidate must be qualified.", candidate.candidateId);
        }
        if (candidate.qualificationEvidenceId.trim().length === 0) {
            add("CANDIDATE_QUALIFICATION_EVIDENCE_MISSING", "Qualification evidence identity is required.", candidate.candidateId);
        }
        if (!candidate.qualificationCurrent) {
            add("CANDIDATE_QUALIFICATION_STALE", "Qualification evidence must be current.", candidate.candidateId);
        }
    }
}
function validatePublicationRecords(publicationRecords, add) {
    if (publicationRecords.length > 0) {
        add("PUBLICATION_RECORDS_PRESENT", "Admission staging requires zero prior, partial, or intermediate publications.");
    }
}
function validateBoundaries(boundaries, candidates, add) {
    if (boundaries.length !== 1) {
        add("BOUNDARY_COUNT_MISMATCH", "Admission requires exactly one staged release boundary.");
    }
    const candidate = candidates.length === 1 ? candidates[0] : null;
    for (const boundary of boundaries) {
        if (boundary.boundaryId.trim().length === 0) {
            add("BOUNDARY_ID_MISSING", "Release boundary identity is required.");
        }
        if (boundary.state !== "staged") {
            add("BOUNDARY_NOT_STAGED", "The release boundary must remain staged.", boundary.boundaryId);
        }
        if (boundary.scope !== "complete-correction") {
            add("BOUNDARY_SCOPE_INCOMPLETE", "The release boundary must cover the complete correction.", boundary.boundaryId);
        }
        if (boundary.published) {
            add("BOUNDARY_ALREADY_PUBLISHED", "The staged release boundary must not be externally published.", boundary.boundaryId);
        }
        if (candidate !== null &&
            (boundary.candidateId !== candidate.candidateId || boundary.version !== candidate.version)) {
            add("BOUNDARY_CANDIDATE_MISMATCH", "Boundary candidate identity and version must match the admitted candidate.", boundary.boundaryId);
        }
    }
}
