"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.allocateGovernedSliceIdentity = allocateGovernedSliceIdentity;
const types_1 = require("./types");
const IMPLEMENTATION_ORDER_PATTERN = /^(?:0\d|[1-9]\d+)$/;
const SLICE_SLUG_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
const SLICE_ID_PATTERN = /^(?:0\d|[1-9]\d+)-[a-z0-9]+(?:-[a-z0-9]+)*$/;
/** Resolves or allocates the ordered identity owned by one Governed slice root. */
function allocateGovernedSliceIdentity(input) {
    const specificationIds = normalizeSpecificationIdentities(input.specificationReferences);
    const implementationOrder = resolveImplementationOrder(input.implementationOrders);
    const sliceSlug = validateSliceSlug(input.sliceSlug);
    const expectedSliceId = `${implementationOrder}-${sliceSlug}`;
    const existingSliceIds = normalizeExistingSliceIds(input.existingSliceIds ?? []);
    const requestedSliceId = normalizeOptionalSliceId(input.requestedSliceId, "requestedSliceId");
    const existingSliceId = normalizeOptionalSliceId(input.existingSliceId, "existingSliceId");
    if (requestedSliceId !== null && existingSliceId !== null) {
        throw new types_1.WorkRoutingError("invalid-slice-identity", "Existing and requested Governed slice identities cannot be supplied together.");
    }
    if (existingSliceId !== null) {
        assertMatchesSourceEvidence(existingSliceId, expectedSliceId, "existingSliceId");
        return {
            sliceId: existingSliceId,
            implementationOrder,
            sliceSlug,
            generated: false,
            preserved: true,
            specificationIds
        };
    }
    const sliceId = requestedSliceId ?? expectedSliceId;
    assertMatchesSourceEvidence(sliceId, expectedSliceId, requestedSliceId === null ? "generated slice identity" : "requestedSliceId");
    if (existingSliceIds.has(sliceId)) {
        throw new types_1.WorkRoutingError("slice-identity-collision", `Governed slice identity '${sliceId}' is already in use.`);
    }
    return {
        sliceId,
        implementationOrder,
        sliceSlug,
        generated: requestedSliceId === null,
        preserved: false,
        specificationIds
    };
}
function resolveImplementationOrder(implementationOrders) {
    if (implementationOrders.length === 0) {
        throw new types_1.WorkRoutingError("missing-implementation-order", "Governed slice identity allocation requires explicit implementation-order evidence.");
    }
    const normalized = implementationOrders.map((order) => {
        if (typeof order !== "string" || !IMPLEMENTATION_ORDER_PATTERN.test(order)) {
            throw new types_1.WorkRoutingError("invalid-slice-identity", "Governed implementation order must be a whole number rendered with at least two digits.");
        }
        return order;
    });
    const distinct = new Set(normalized);
    if (distinct.size !== 1) {
        throw new types_1.WorkRoutingError("conflicting-implementation-order", `Governed slice identity received conflicting implementation orders: ${[...distinct].join(", ")}.`);
    }
    return normalized[0];
}
function validateSliceSlug(sliceSlug) {
    if (typeof sliceSlug !== "string" || !SLICE_SLUG_PATTERN.test(sliceSlug)) {
        throw new types_1.WorkRoutingError("invalid-slice-identity", "Governed slice slug must be a lowercase kebab-case identifier.");
    }
    return sliceSlug;
}
function normalizeOptionalSliceId(sliceId, field) {
    if (sliceId === undefined || sliceId === null)
        return null;
    return validateSliceId(sliceId, field);
}
function normalizeExistingSliceIds(existingSliceIds) {
    const normalized = new Set();
    for (const sliceId of existingSliceIds) {
        normalized.add(validateSliceId(sliceId, "existingSliceIds"));
    }
    return normalized;
}
function validateSliceId(sliceId, field) {
    if (typeof sliceId !== "string" || !SLICE_ID_PATTERN.test(sliceId)) {
        throw new types_1.WorkRoutingError("invalid-slice-identity", `Governed slice identity from '${field}' must match '<ordered-prefix>-<slice-slug>' with an order of at least two digits.`);
    }
    return sliceId;
}
function assertMatchesSourceEvidence(sliceId, expectedSliceId, field) {
    if (sliceId !== expectedSliceId) {
        throw new types_1.WorkRoutingError("invalid-slice-identity", `Governed slice identity from '${field}' conflicts with explicit order and slug evidence; expected '${expectedSliceId}'.`);
    }
}
function normalizeSpecificationIdentities(specificationReferences) {
    if (specificationReferences.length === 0) {
        throw new types_1.WorkRoutingError("invalid-specification-input", "Governed slice identity requires resolved canonical specification references.");
    }
    const specificationIds = specificationReferences
        .map((reference) => reference.specId)
        .sort((left, right) => left.localeCompare(right));
    if (specificationIds.some((specId) => specId.trim() === "")) {
        throw new types_1.WorkRoutingError("invalid-specification-input", "Governed slice identity requires non-empty canonical specification identities.");
    }
    if (new Set(specificationIds).size !== specificationIds.length) {
        throw new types_1.WorkRoutingError("duplicate-specification-identity", "Governed slice identity allocation received duplicate canonical specification identities.");
    }
    return specificationIds;
}
