"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.UnavailableWorkerConfigOverrideError = exports.THINKING_WORKERS_CONFIG_OVERRIDE_PATH = exports.DEFAULT_WORKERS_CONFIG_OVERRIDE_PATH = void 0;
exports.isConfigOverrideEntryValid = isConfigOverrideEntryValid;
exports.assertConfigOverrideEntryValid = assertConfigOverrideEntryValid;
exports.hasUnavailableWorkerConfigOverride = hasUnavailableWorkerConfigOverride;
exports.findUnavailableWorkerConfigOverride = findUnavailableWorkerConfigOverride;
exports.assertNoUnavailableWorkerConfigOverride = assertNoUnavailableWorkerConfigOverride;
const control_plane_config_1 = require("../config/control-plane-config");
const issue_override_option_registry_1 = require("./issue-override-option-registry");
const types_1 = require("./types");
exports.DEFAULT_WORKERS_CONFIG_OVERRIDE_PATH = "workers.default";
exports.THINKING_WORKERS_CONFIG_OVERRIDE_PATH = "workers.thinking";
const WORKER_CONFIG_OVERRIDE_PATHS = new Set([
    exports.DEFAULT_WORKERS_CONFIG_OVERRIDE_PATH,
    exports.THINKING_WORKERS_CONFIG_OVERRIDE_PATH,
]);
class UnavailableWorkerConfigOverrideError extends Error {
    worker;
    constructor(worker) {
        super(`Worker override is not configured: ${worker}`);
        this.worker = worker;
        this.name = "UnavailableWorkerConfigOverrideError";
    }
}
exports.UnavailableWorkerConfigOverrideError = UnavailableWorkerConfigOverrideError;
function isConfigOverrideEntryValid(entry) {
    return getConfigOverrideEntryValidationError(entry) === null;
}
function assertConfigOverrideEntryValid(entry) {
    const error = getConfigOverrideEntryValidationError(entry);
    if (error !== null) {
        throw new Error(error);
    }
}
function hasUnavailableWorkerConfigOverride(input) {
    return findUnavailableWorkerConfigOverride(input) !== null;
}
function findUnavailableWorkerConfigOverride(input) {
    for (const entry of input.patch?.entries ?? []) {
        if (!WORKER_CONFIG_OVERRIDE_PATHS.has(entry.path) ||
            entry.op !== "set" ||
            !Array.isArray(entry.value) ||
            entry.value.length !== 1) {
            continue;
        }
        const [worker] = entry.value;
        if (typeof worker === "string" && !input.configWorkers.includes(worker)) {
            return worker;
        }
    }
    return null;
}
function assertNoUnavailableWorkerConfigOverride(input) {
    const worker = findUnavailableWorkerConfigOverride(input);
    if (worker !== null) {
        throw new UnavailableWorkerConfigOverrideError(worker);
    }
}
function getConfigOverrideEntryValidationError(entry) {
    const option = issue_override_option_registry_1.ISSUE_OVERRIDE_OPTION_REGISTRY_BY_PATH.get(entry.path);
    if (option === undefined) {
        return `Unsupported config override path: ${entry.path}`;
    }
    switch (entry.op) {
        case "inherit":
            return null;
        case "disable":
            return isOperationOverrideAllowed(option)
                ? null
                : `Config override ${entry.op} is not supported for ${entry.path}`;
        case "set":
            return isSetOverrideValueValid(option, entry.value)
                ? null
                : `Config override value does not match ${entry.path} ${option.kind} type`;
    }
}
function isOperationOverrideAllowed(option) {
    return option.allowDisable === true;
}
function isSetOverrideValueValid(option, value) {
    switch (option.kind) {
        case "boolean":
            return typeof value === "boolean";
        case "integer":
            return (typeof value === "number" &&
                Number.isInteger(value) &&
                Number.isFinite(value) &&
                (option.min === undefined || value >= option.min) &&
                (option.max === undefined || value <= option.max));
        case "number":
            return (typeof value === "number" &&
                Number.isFinite(value) &&
                (option.min === undefined || value >= option.min) &&
                (option.max === undefined || value <= option.max));
        case "enum":
            return (typeof value === "string" &&
                (option.enumValues?.includes(value) ?? false));
        case "string":
            return typeof value === "string";
        case "string-array":
            return (Array.isArray(value) &&
                value.every((entry) => typeof entry === "string"));
        case "workflow-template-list":
            return (Array.isArray(value) &&
                value.every((entry) => typeof entry === "string" &&
                    (0, types_1.normalizeFollowupWorkflowTemplateCandidate)(entry) !== null));
        case "worker":
            return (Array.isArray(value) &&
                value.length === 1 &&
                typeof value[0] === "string" &&
                isValidWorkerOverrideName(value[0]));
    }
}
function isValidWorkerOverrideName(worker) {
    return ((0, control_plane_config_1.isBuiltInWorkerName)(worker) ||
        control_plane_config_1.customWorkerIdSchema.safeParse(worker).success);
}
