"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.coerceWorkflowParentRef = coerceWorkflowParentRef;
exports.coerceWorkflowParentLink = coerceWorkflowParentLink;
exports.coerceWorkflowContract = coerceWorkflowContract;
exports.coerceWorkflowExecutionContract = coerceWorkflowExecutionContract;
exports.coerceWorkflowChildBindingHints = coerceWorkflowChildBindingHints;
exports.coerceWorkflowIssueChildKey = coerceWorkflowIssueChildKey;
exports.coerceWorkflowOriginLink = coerceWorkflowOriginLink;
exports.hasOnlyRecordKeys = hasOnlyRecordKeys;
exports.coerceWorkflowSelectionState = coerceWorkflowSelectionState;
exports.coerceWorkflowTemplateSelector = coerceWorkflowTemplateSelector;
exports.coerceWorkflowTemplateResolution = coerceWorkflowTemplateResolution;
exports.coerceWorkflowTemplateBindings = coerceWorkflowTemplateBindings;
exports.coerceWorkflowStartApprovalIntent = coerceWorkflowStartApprovalIntent;
exports.coerceWorkflowPendingPlanningIntent = coerceWorkflowPendingPlanningIntent;
exports.coerceWorkflowPendingPlanningSource = coerceWorkflowPendingPlanningSource;
exports.coerceWorkflowSurface = coerceWorkflowSurface;
exports.coerceNullableWorkflowTemplateSelector = coerceNullableWorkflowTemplateSelector;
exports.coerceWorkflowScheduleState = coerceWorkflowScheduleState;
exports.normalizeWorkflowScheduleState = normalizeWorkflowScheduleState;
exports.coerceWorkflowScheduledRunState = coerceWorkflowScheduledRunState;
exports.coerceWorkflowResult = coerceWorkflowResult;
exports.coerceWorkflowFinalResult = coerceWorkflowFinalResult;
exports.coerceWorkflowResultOutcome = coerceWorkflowResultOutcome;
exports.coerceConsecutiveAiRuns = coerceConsecutiveAiRuns;
exports.coerceTotalAiRunHours = coerceTotalAiRunHours;
exports.coerceWorkflowPriorityRank = coerceWorkflowPriorityRank;
exports.coerceNullableString = coerceNullableString;
exports.coerceArrayItems = coerceArrayItems;
exports.coerceStringArray = coerceStringArray;
exports.isRecord = isRecord;
exports.isNullableString = isNullableString;
const default_system_workflows_1 = require("../default-system-workflows");
const types_1 = require("../types");
function coerceWorkflowParentRef(value) {
    if (value === undefined) {
        return undefined;
    }
    if (value === null) {
        return null;
    }
    if (typeof value !== "string") {
        return undefined;
    }
    const normalized = normalizeNullableText(value);
    if (normalized === null) {
        return undefined;
    }
    return /^#\d+$/u.test(normalized) ? normalized : undefined;
}
function coerceWorkflowParentLink(value) {
    if (value === undefined) {
        return undefined;
    }
    if (!isRecord(value)) {
        return null;
    }
    const parentLink = value;
    const parentRef = coerceWorkflowParentRef(parentLink.parentRef);
    const childKey = coerceWorkflowIssueChildKey(parentLink.childKey);
    if (!hasOnlyRecordKeys(parentLink, PARENT_LINK_FIELD_NAMES) ||
        parentRef === undefined ||
        parentRef === null ||
        childKey === null) {
        return null;
    }
    return {
        parentRef,
        childKey,
    };
}
function coerceWorkflowContract(value) {
    if (value === undefined) {
        return undefined;
    }
    if (!isRecord(value)) {
        return null;
    }
    const contract = value;
    if (contract.objective !== undefined &&
        contract.objective !== null &&
        typeof contract.objective !== "string") {
        return null;
    }
    const objective = normalizeNullableText(contract.objective);
    const instructions = contract.instructions === undefined
        ? []
        : coerceStringArray(contract.instructions);
    const doneWhen = coerceStringArray(contract.doneWhen);
    const inputs = coerceStringArray(contract.inputs);
    const outputs = coerceStringArray(contract.outputs);
    if (objective === null ||
        instructions === null ||
        doneWhen === null ||
        inputs === null ||
        outputs === null) {
        return null;
    }
    return {
        objective,
        ...(instructions.length > 0 ? { instructions } : {}),
        doneWhen,
        inputs,
        outputs,
    };
}
function coerceWorkflowExecutionContract(value) {
    if (value === undefined) {
        return undefined;
    }
    if (!isRecord(value)) {
        return null;
    }
    if (!hasOnlyRecordKeys(value, EXECUTION_CONTRACT_FIELD_NAMES)) {
        return null;
    }
    const contract = value;
    const baseContract = coerceWorkflowContract(contract);
    if (baseContract === undefined || baseContract === null) {
        return null;
    }
    return baseContract;
}
function coerceWorkflowChildBindingHints(value) {
    if (value === undefined) {
        return undefined;
    }
    if (value === null) {
        return null;
    }
    if (!isRecord(value)) {
        return null;
    }
    const bindingHints = value;
    if ((bindingHints.milestoneRef !== undefined &&
        !isNullableString(bindingHints.milestoneRef)) ||
        (bindingHints.projectRef !== undefined &&
            !isNullableString(bindingHints.projectRef))) {
        return null;
    }
    return {
        ...(bindingHints.milestoneRef !== undefined
            ? { milestoneRef: coerceNullableString(bindingHints.milestoneRef) }
            : {}),
        ...(bindingHints.projectRef !== undefined
            ? { projectRef: coerceNullableString(bindingHints.projectRef) }
            : {}),
    };
}
function normalizeRequiredWorkflowChildText(value) {
    const normalized = normalizeNullableText(value);
    return normalized === null ? null : normalized;
}
function coerceWorkflowIssueChildKey(value) {
    return normalizeRequiredWorkflowChildText(value);
}
function coerceWorkflowOriginLink(value) {
    if (value === undefined) {
        return undefined;
    }
    if (!isRecord(value) || !hasOnlyRecordKeys(value, ORIGIN_LINK_FIELD_NAMES)) {
        return null;
    }
    const originLink = value;
    if (originLink.kind !== "followup" ||
        typeof originLink.sourceIssueId !== "string" ||
        typeof originLink.sourceIssueDisplayId !== "string" ||
        typeof originLink.sourceIssueUrl !== "string" ||
        typeof originLink.followupRequestDigest !== "string" ||
        typeof originLink.followupRequestTitle !== "string") {
        return null;
    }
    const sourceIssueId = normalizeNullableText(originLink.sourceIssueId);
    const sourceIssueDisplayId = normalizeNullableText(originLink.sourceIssueDisplayId);
    const sourceIssueUrl = normalizeNullableText(originLink.sourceIssueUrl);
    const followupRequestDigest = normalizeNullableText(originLink.followupRequestDigest);
    const followupRequestTitle = normalizeNullableText(originLink.followupRequestTitle);
    if (sourceIssueId === null ||
        sourceIssueDisplayId === null ||
        sourceIssueUrl === null ||
        followupRequestDigest === null ||
        followupRequestTitle === null) {
        return null;
    }
    return {
        kind: "followup",
        sourceIssueId,
        sourceIssueDisplayId,
        sourceIssueUrl,
        followupRequestDigest,
        followupRequestTitle,
    };
}
function hasOnlyRecordKeys(value, allowedKeys) {
    return Object.keys(value).every((key) => allowedKeys.has(key));
}
const PARENT_LINK_FIELD_NAMES = new Set(["parentRef", "childKey"]);
const ORIGIN_LINK_FIELD_NAMES = new Set([
    "kind",
    "sourceIssueId",
    "sourceIssueDisplayId",
    "sourceIssueUrl",
    "followupRequestDigest",
    "followupRequestTitle",
]);
const EXECUTION_CONTRACT_FIELD_NAMES = new Set([
    "objective",
    "instructions",
    "doneWhen",
    "inputs",
    "outputs",
]);
const WORKFLOW_TEMPLATE_SELECTOR_MODE_FIELD_NAMES = new Set(["mode"]);
const WORKFLOW_TEMPLATE_SELECTOR_TEMPLATE_FIELD_NAMES = new Set([
    "mode",
    "templatePath",
]);
const WORKFLOW_TEMPLATE_RESOLUTION_NONE_FIELD_NAMES = new Set(["kind"]);
const WORKFLOW_TEMPLATE_RESOLUTION_TEMPLATE_FIELD_NAMES = new Set([
    "kind",
    "templatePath",
    "digest",
]);
const WORKFLOW_RESULT_FIELD_NAMES = new Set([
    "outcome",
    "resultSummary",
    "evidence",
    "humanComment",
]);
function coerceWorkflowSelectionState(value) {
    return coerceWorkflowTemplateSelector(value);
}
function coerceWorkflowTemplateSelector(value) {
    if (!isRecord(value)) {
        return null;
    }
    const selection = value;
    if (selection.mode !== "auto" &&
        selection.mode !== "auto_select" &&
        selection.mode !== "no_template" &&
        selection.mode !== "template") {
        return null;
    }
    if (selection.mode === "auto" ||
        selection.mode === "auto_select" ||
        selection.mode === "no_template") {
        if (!hasOnlyRecordKeys(value, WORKFLOW_TEMPLATE_SELECTOR_MODE_FIELD_NAMES)) {
            return null;
        }
        return { mode: selection.mode };
    }
    if (!hasOnlyRecordKeys(value, WORKFLOW_TEMPLATE_SELECTOR_TEMPLATE_FIELD_NAMES)) {
        return null;
    }
    if (typeof selection.templatePath !== "string") {
        return null;
    }
    const normalizedTemplatePath = (0, types_1.normalizeWorkflowTemplatePath)(selection.templatePath);
    if (normalizedTemplatePath === null) {
        return null;
    }
    return { mode: "template", templatePath: normalizedTemplatePath };
}
function coerceWorkflowTemplateResolution(value) {
    if (!isRecord(value)) {
        return null;
    }
    const resolution = value;
    if (resolution.kind === "none") {
        if (!hasOnlyRecordKeys(value, WORKFLOW_TEMPLATE_RESOLUTION_NONE_FIELD_NAMES)) {
            return null;
        }
        return { kind: "none" };
    }
    if (!hasOnlyRecordKeys(value, WORKFLOW_TEMPLATE_RESOLUTION_TEMPLATE_FIELD_NAMES)) {
        return null;
    }
    if (resolution.kind !== "template" ||
        typeof resolution.templatePath !== "string" ||
        typeof resolution.digest !== "string") {
        return null;
    }
    const normalizedTemplatePath = (0, types_1.normalizeWorkflowTemplatePath)(resolution.templatePath);
    if (normalizedTemplatePath === null) {
        return null;
    }
    return {
        kind: "template",
        templatePath: normalizedTemplatePath,
        digest: resolution.digest,
    };
}
function coerceWorkflowTemplateBindings(value) {
    if (!isRecord(value)) {
        return null;
    }
    const record = value;
    const keys = Object.keys(record);
    if (keys.length !== types_1.WORKFLOW_TEMPLATE_TARGETS.length ||
        !types_1.WORKFLOW_TEMPLATE_TARGETS.every((surface) => Object.hasOwn(record, surface))) {
        return null;
    }
    const bindings = Object.fromEntries(types_1.WORKFLOW_TEMPLATE_TARGETS.map((surface) => [
        surface,
        coerceWorkflowTemplateBinding(record[surface]),
    ]));
    if (types_1.WORKFLOW_TEMPLATE_TARGETS.some((surface) => bindings[surface] === null)) {
        return null;
    }
    return bindings;
}
function coerceWorkflowTemplateBinding(value) {
    if (!isRecord(value)) {
        return null;
    }
    if (Object.keys(value).length !== 2 ||
        !Object.hasOwn(value, "selector") ||
        !Object.hasOwn(value, "resolution")) {
        return null;
    }
    const binding = value;
    const selector = coerceWorkflowTemplateSelector(binding.selector);
    const resolution = coerceWorkflowTemplateResolution(binding.resolution);
    if (selector === null || resolution === null) {
        return null;
    }
    if (!isCoercedWorkflowTemplateBindingConsistent(selector, resolution)) {
        return null;
    }
    return { selector, resolution };
}
function isCoercedWorkflowTemplateBindingConsistent(selector, resolution) {
    if (selector.mode === "no_template") {
        return (resolution.kind === "template" &&
            (0, default_system_workflows_1.isDefaultSystemWorkflowTemplatePath)(resolution.templatePath));
    }
    if (selector.mode === "template" && resolution.kind === "template") {
        return selector.templatePath === resolution.templatePath;
    }
    return true;
}
function coerceWorkflowStartApprovalIntent(value) {
    if (value === undefined) {
        return undefined;
    }
    if (value !== null && typeof value !== "string") {
        return null;
    }
    const normalized = normalizeNullableText(value);
    if (normalized === null) {
        return null;
    }
    return types_1.WORKFLOW_START_APPROVAL_INTENT_VALUES.includes(normalized)
        ? normalized
        : null;
}
function coerceWorkflowPendingPlanningIntent(value) {
    if (value === undefined) {
        return undefined;
    }
    if (value !== null && typeof value !== "string") {
        return null;
    }
    const normalized = normalizeNullableText(value);
    if (normalized === null) {
        return null;
    }
    return types_1.WORKFLOW_PENDING_PLANNING_INTENT_VALUES.includes(normalized)
        ? normalized
        : null;
}
function coerceWorkflowPendingPlanningSource(value) {
    if (value === undefined) {
        return undefined;
    }
    if (value !== null && typeof value !== "string") {
        return null;
    }
    const normalized = normalizeNullableText(value);
    if (normalized === null) {
        return null;
    }
    return types_1.WORKFLOW_PENDING_PLANNING_SOURCE_VALUES.includes(normalized)
        ? normalized
        : null;
}
function coerceWorkflowSurface(value) {
    if (typeof value !== "string") {
        return null;
    }
    return types_1.WORKFLOW_SURFACES.includes(value)
        ? value
        : null;
}
function coerceNullableWorkflowTemplateSelector(value) {
    if (value === undefined) {
        return undefined;
    }
    if (value === null) {
        return null;
    }
    if (typeof value !== "string") {
        return null;
    }
    const normalized = (0, types_1.normalizeWorkflowTemplatePath)(value);
    if (normalized === null) {
        return null;
    }
    return normalized;
}
function coerceWorkflowScheduleState(value) {
    if (value === undefined) {
        return null;
    }
    if (!isRecord(value)) {
        return null;
    }
    const schedule = value;
    if (schedule.mode === "off") {
        if (schedule.value !== null &&
            schedule.value !== undefined &&
            schedule.value !== "") {
            return null;
        }
        return (0, types_1.createOffWorkflowScheduleState)();
    }
    if (schedule.mode !== "every" && schedule.mode !== "cron") {
        return null;
    }
    if (typeof schedule.value !== "string" ||
        schedule.value.trim().length === 0) {
        return null;
    }
    return {
        mode: schedule.mode,
        value: schedule.value.trim(),
    };
}
function normalizeWorkflowScheduleState(value) {
    return value ?? (0, types_1.createOffWorkflowScheduleState)();
}
function coerceWorkflowScheduledRunState(value) {
    if (value === undefined) {
        return undefined;
    }
    if (!isRecord(value)) {
        return null;
    }
    const scheduledRun = value;
    const requestedBy = scheduledRun.requestedBy;
    const requestedValue = scheduledRun.requestedValue;
    if (scheduledRun.kind !== "one_shot" ||
        typeof scheduledRun.runAt !== "string" ||
        typeof scheduledRun.requestedAt !== "string" ||
        typeof requestedValue !== "string" ||
        !Number.isFinite(Date.parse(scheduledRun.runAt)) ||
        !Number.isFinite(Date.parse(scheduledRun.requestedAt))) {
        return null;
    }
    const base = {
        kind: "one_shot",
        runAt: new Date(Date.parse(scheduledRun.runAt)).toISOString(),
        requestedAt: new Date(Date.parse(scheduledRun.requestedAt)).toISOString(),
    };
    if (requestedBy === "run_at" || requestedBy === "run_after") {
        return {
            ...base,
            requestedBy,
            requestedValue,
        };
    }
    if (requestedBy === "cooldown" &&
        (requestedValue === "quota_exhausted" || requestedValue === "capacity")) {
        return {
            ...base,
            requestedBy,
            requestedValue,
        };
    }
    return null;
}
function coerceWorkflowResult(value) {
    if (value === null || value === undefined) {
        return null;
    }
    if (!isRecord(value)) {
        return null;
    }
    if (!hasOnlyRecordKeys(value, WORKFLOW_RESULT_FIELD_NAMES)) {
        return null;
    }
    const parsedResult = value;
    if (typeof parsedResult.outcome !== "string" ||
        !isWorkflowResultOutcome(parsedResult.outcome)) {
        return null;
    }
    if (typeof parsedResult.resultSummary !== "string" ||
        parsedResult.resultSummary.length === 0) {
        return null;
    }
    const evidence = coerceStringArrayOrNull(parsedResult.evidence);
    if (evidence === null) {
        return null;
    }
    const normalizedResult = (0, types_1.buildWorkflowResultWithDefaults)({
        outcome: parsedResult.outcome,
        resultSummary: parsedResult.resultSummary,
        evidence,
        humanComment: coerceNullableString(parsedResult.humanComment),
    });
    return normalizedResult;
}
function coerceWorkflowFinalResult(value) {
    const result = coerceWorkflowResult(value);
    if (result === null || !isWorkflowFinalResultOutcome(result.outcome)) {
        return null;
    }
    const normalizedResult = (0, types_1.buildWorkflowFinalResultWithDefaults)(result);
    return normalizedResult;
}
function coerceWorkflowResultOutcome(value) {
    if (value === undefined || value === null) {
        return null;
    }
    return types_1.WORKFLOW_RESULT_OUTCOMES.includes(value)
        ? value
        : null;
}
function isWorkflowResultOutcome(value) {
    return types_1.WORKFLOW_RESULT_OUTCOMES.includes(value);
}
function isWorkflowFinalResultOutcome(value) {
    return types_1.WORKFLOW_FINAL_RESULT_OUTCOMES.includes(value);
}
function coerceConsecutiveAiRuns(value) {
    return typeof value === "number" && Number.isInteger(value) && value >= 0
        ? value
        : 0;
}
function coerceTotalAiRunHours(value) {
    return typeof value === "number" && Number.isFinite(value) && value >= 0
        ? value
        : 0;
}
function coerceWorkflowPriorityRank(value) {
    if (value === undefined || value === null) {
        return null;
    }
    return typeof value === "number" && Number.isSafeInteger(value) && value >= 0
        ? value
        : undefined;
}
function coerceNullableString(value) {
    return typeof value === "string" ? value : value === null ? null : null;
}
function coerceArrayItems(value, coerceItem) {
    if (!Array.isArray(value)) {
        return null;
    }
    const entries = [];
    for (const entry of value) {
        const coercedEntry = coerceItem(entry);
        if (coercedEntry === null) {
            return null;
        }
        entries.push(coercedEntry);
    }
    return entries;
}
function normalizeNullableText(value) {
    if (typeof value !== "string") {
        return value === null || value === undefined ? null : null;
    }
    const text = value.trim();
    return text.length === 0 || text === "-" ? null : text;
}
function coerceStringArray(value) {
    if (!Array.isArray(value) ||
        value.some((entry) => typeof entry !== "string")) {
        return null;
    }
    return [...value];
}
function coerceStringArrayOrNull(value) {
    if (value === undefined) {
        return [];
    }
    if (value === null) {
        return [];
    }
    return coerceStringArray(value);
}
function isRecord(value) {
    return typeof value === "object" && value !== null;
}
function isNullableString(value) {
    return typeof value === "string" || value === null;
}
