"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.allocateWorkIdentity = allocateWorkIdentity;
const types_1 = require("./types");
const WORK_ID_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
/** Resolves Basic no-work identity or a Structured level-local work identity. */
function allocateWorkIdentity(input) {
    if (input.level === "basic")
        return resolveBasicIdentity(input);
    if (input.level === "governed") {
        throw new types_1.WorkRoutingError("invalid-work-identity", "Governed planning owns an ordered slice identity; use allocateGovernedSliceIdentity instead.");
    }
    const specificationIds = normalizeSpecificationIdentities(input);
    const existingWorkIds = normalizeExistingWorkIds(input.existingWorkIds ?? []);
    if (input.existingWorkId !== undefined && input.existingWorkId !== null) {
        if (input.requestedWorkId !== undefined && input.requestedWorkId !== null) {
            throw new types_1.WorkRoutingError("invalid-work-identity", "Existing and requested work identities cannot be supplied together.");
        }
        return {
            workId: validateWorkId(input.existingWorkId, "existingWorkId"),
            generated: false,
            preserved: true,
            collisionOrdinal: null,
            specificationIds
        };
    }
    if (input.requestedWorkId !== undefined && input.requestedWorkId !== null) {
        const requestedWorkId = validateWorkId(input.requestedWorkId, "requestedWorkId");
        if (existingWorkIds.has(requestedWorkId)) {
            throw new types_1.WorkRoutingError("work-identity-collision", `Requested work identity '${requestedWorkId}' is already in use.`);
        }
        return {
            workId: requestedWorkId,
            generated: false,
            preserved: false,
            collisionOrdinal: 1,
            specificationIds
        };
    }
    const base = generatedBaseIdentity(specificationIds);
    let collisionOrdinal = 1;
    let workId = base;
    while (existingWorkIds.has(workId)) {
        collisionOrdinal += 1;
        workId = `${base}-${collisionOrdinal}`;
    }
    return {
        workId,
        generated: true,
        preserved: false,
        collisionOrdinal,
        specificationIds
    };
}
function resolveBasicIdentity(input) {
    if (input.specificationReferences.length > 0 ||
        input.requestedWorkId !== undefined && input.requestedWorkId !== null ||
        input.existingWorkId !== undefined && input.existingWorkId !== null) {
        throw new types_1.WorkRoutingError("invalid-work-identity", "Basic task routing must not allocate, request, or preserve a work identity.");
    }
    return {
        workId: null,
        generated: false,
        preserved: false,
        collisionOrdinal: null,
        specificationIds: []
    };
}
function normalizeSpecificationIdentities(input) {
    if (input.specificationReferences.length === 0) {
        throw new types_1.WorkRoutingError("invalid-specification-input", `${capitalize(input.level)} work identity requires resolved canonical specification references.`);
    }
    const specificationIds = input.specificationReferences
        .map((reference) => reference.specId)
        .sort((left, right) => left.localeCompare(right));
    const uniqueIdentities = new Set(specificationIds);
    if (uniqueIdentities.size !== specificationIds.length) {
        throw new types_1.WorkRoutingError("duplicate-specification-identity", "Work identity allocation received duplicate canonical specification identities.");
    }
    if (specificationIds.some((specId) => specId.trim() === "")) {
        throw new types_1.WorkRoutingError("invalid-specification-input", "Work identity allocation requires non-empty canonical specification identities.");
    }
    return specificationIds;
}
function normalizeExistingWorkIds(existingWorkIds) {
    const normalized = new Set();
    for (const workId of existingWorkIds)
        normalized.add(validateWorkId(workId, "existingWorkIds"));
    return normalized;
}
function validateWorkId(value, field) {
    if (!WORK_ID_PATTERN.test(value)) {
        throw new types_1.WorkRoutingError("invalid-work-identity", `Work identity from '${field}' must be a lowercase kebab-case identifier.`);
    }
    return value;
}
function generatedBaseIdentity(specificationIds) {
    if (specificationIds.length !== 1) {
        throw new types_1.WorkRoutingError("invalid-work-identity", "Structured work sourced from multiple specifications requires an explicit --work-id so its user-facing path remains meaningful.");
    }
    return validateWorkId(specificationIds[0], "specificationReferences");
}
function capitalize(value) {
    return `${value.slice(0, 1).toUpperCase()}${value.slice(1)}`;
}
