import { asRecord, normalizeText } from './utils.js';
import { createSelectorReadError } from './world-evolution-selector-read-errors.js';
const EXECUTION_STAGES = new Set([
    'INGRESS',
    'NORMALIZE',
    'SCHEDULE',
    'DISPATCH',
    'TRANSITION',
    'EFFECT',
    'COMMIT_REQUEST',
    'CHECKPOINT',
    'TERMINAL',
]);
const EXECUTION_EVENT_KINDS = new Set([
    'EXECUTION_EVENT',
]);
const EFFECT_CLASSES = new Set([
    'NONE',
    'STATE_ONLY',
    'STATE_AND_HISTORY',
]);
const SUPERVISION_OUTCOMES = new Set([
    'CONTINUE',
    'DEFER',
    'ABORT',
    'QUARANTINE',
]);
const REPLAY_MODES = new Set(['RECORDED']);
const COMMON_FORBIDDEN_VIEW_KEYS = new Set([
    'workflow',
    'task',
    'node',
    'edge',
    'callback_ref',
    'external_async',
    'route_policy',
    'fallback',
    'runMode',
]);
function listUnexpectedKeys(record, allowed) {
    return Object.keys(record).filter((key) => !allowed.has(key));
}
export function normalizeRequiredText(value, fieldName, category, methodId) {
    const normalized = normalizeText(value);
    if (!normalized) {
        throw createSelectorReadError({
            category,
            methodId,
            message: `${methodId} requires ${fieldName}`,
        });
    }
    return normalized;
}
export function normalizeOptionalText(value) {
    const normalized = normalizeText(value);
    return normalized || undefined;
}
export function normalizeReplayMode(value, category, methodId) {
    const replayMode = normalizeRequiredText(value, 'replayMode', category, methodId);
    if (!REPLAY_MODES.has(replayMode)) {
        throw createSelectorReadError({
            category,
            methodId,
            message: `${methodId} only admits replayMode RECORDED`,
        });
    }
    return replayMode;
}
export function normalizeTick(value, fieldName, category, methodId) {
    if (typeof value !== 'number' || !Number.isInteger(value) || value < 0) {
        throw createSelectorReadError({
            category,
            methodId,
            message: `${methodId} requires ${fieldName} to be a non-negative integer`,
        });
    }
    return value;
}
export function normalizeActorRefs(value, category, methodId) {
    if (!Array.isArray(value) || value.length === 0) {
        throw createSelectorReadError({
            category,
            methodId,
            message: `${methodId} requires actorRefs to be a non-empty array`,
        });
    }
    return value.map((item) => {
        const record = asRecord(item);
        const actorId = normalizeRequiredText(record.actorId, 'actorRefs.actorId', category, methodId);
        const actorType = normalizeRequiredText(record.actorType, 'actorRefs.actorType', category, methodId);
        const role = normalizeOptionalText(record.role);
        return role ? { actorId, actorType, role } : { actorId, actorType };
    });
}
export function normalizeEvidenceRefs(value, category, methodId) {
    if (!Array.isArray(value) || value.length === 0) {
        throw createSelectorReadError({
            category,
            methodId,
            message: `${methodId} requires evidenceRefs to be a non-empty array`,
        });
    }
    return value.map((item) => normalizeEvidenceRef(item, category, methodId));
}
export function normalizeEvidenceRef(value, category, methodId) {
    const record = asRecord(value);
    const kind = normalizeRequiredText(record.kind, 'evidenceRef.kind', category, methodId);
    const refId = normalizeRequiredText(record.refId, 'evidenceRef.refId', category, methodId);
    const uri = normalizeOptionalText(record.uri);
    return uri ? { kind, refId, uri } : { kind, refId };
}
export function normalizeStringArray(value, fieldName, category, methodId) {
    if (!Array.isArray(value) || value.length === 0) {
        throw createSelectorReadError({
            category,
            methodId,
            message: `${methodId} requires ${fieldName} to be a non-empty array`,
        });
    }
    return value.map((entry) => normalizeRequiredText(entry, fieldName, category, methodId));
}
export function normalizeEffectClass(value, category, methodId) {
    const normalized = normalizeRequiredText(value, 'effectClass', category, methodId);
    if (!EFFECT_CLASSES.has(normalized)) {
        throw createSelectorReadError({
            category,
            methodId,
            message: `${methodId} received unsupported effectClass`,
        });
    }
    return normalized;
}
export function normalizeEventKind(value, category, methodId) {
    const normalized = normalizeRequiredText(value, 'eventKind', category, methodId);
    if (!EXECUTION_EVENT_KINDS.has(normalized)) {
        throw createSelectorReadError({
            category,
            methodId,
            message: `${methodId} received unsupported eventKind`,
        });
    }
    return normalized;
}
export function normalizeStage(value, category, methodId) {
    const normalized = normalizeRequiredText(value, 'stage', category, methodId);
    if (!EXECUTION_STAGES.has(normalized)) {
        throw createSelectorReadError({
            category,
            methodId,
            message: `${methodId} received unsupported stage`,
        });
    }
    return normalized;
}
export function normalizeSupervisionOutcome(value, category, methodId) {
    const normalized = normalizeRequiredText(value, 'supervisionOutcome', category, methodId);
    if (!SUPERVISION_OUTCOMES.has(normalized)) {
        throw createSelectorReadError({
            category,
            methodId,
            message: `${methodId} received unsupported supervision outcome`,
        });
    }
    return normalized;
}
export function assertNoUnexpectedKeys(input, allowed, methodId) {
    const unexpectedKeys = listUnexpectedKeys(input, allowed);
    if (unexpectedKeys.length > 0) {
        throw createSelectorReadError({
            category: 'INVALID_SELECTOR',
            methodId,
            message: `${methodId} received unsupported selector primitive`,
            details: { unexpectedKeys },
        });
    }
}
export function hasAnyKey(input, keys) {
    return keys.some((key) => input[key] !== undefined);
}
export function countPresentKeys(input, keys) {
    return keys.filter((key) => input[key] !== undefined).length;
}
export function ensureArray(value, methodId) {
    if (!Array.isArray(value)) {
        throw createSelectorReadError({
            category: 'UNSUPPORTED_PROJECTION_SHAPE',
            methodId,
            message: `${methodId} requires an array of matches`,
        });
    }
    return value;
}
export function assertAllowedViewKeys(record, allowed, methodId) {
    const keys = Object.keys(record);
    const forbiddenKeys = keys.filter((key) => COMMON_FORBIDDEN_VIEW_KEYS.has(key));
    if (forbiddenKeys.length > 0) {
        throw createSelectorReadError({
            category: 'UNSUPPORTED_PROJECTION_SHAPE',
            methodId,
            message: `${methodId} received forbidden projection keys`,
            details: { forbiddenKeys },
        });
    }
    const unexpectedKeys = keys.filter((key) => !allowed.has(key));
    if (unexpectedKeys.length > 0) {
        throw createSelectorReadError({
            category: 'UNSUPPORTED_PROJECTION_SHAPE',
            methodId,
            message: `${methodId} received unsupported projection keys`,
            details: { unexpectedKeys },
        });
    }
}
//# sourceMappingURL=world-evolution-selector-read-shared.js.map