"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.WORKFLOW_LABEL_KEYS = exports.DEFAULT_WORKFLOW_LABELS = void 0;
exports.resolveWorkflowLabels = resolveWorkflowLabels;
exports.buildWorkflowLabelDefinitions = buildWorkflowLabelDefinitions;
exports.buildManagedLabelDefinitions = buildManagedLabelDefinitions;
exports.getFollowupRequestLabelName = getFollowupRequestLabelName;
exports.getNonFollowupManagedLabelNames = getNonFollowupManagedLabelNames;
exports.getAuxiliaryManagedLabelNames = getAuxiliaryManagedLabelNames;
exports.diffWorkflowLabelDefinitions = diffWorkflowLabelDefinitions;
exports.getWorkflowLabelForStatus = getWorkflowLabelForStatus;
exports.getWorkflowLabelForRule = getWorkflowLabelForRule;
exports.parseWorkflowStateFromLabelNames = parseWorkflowStateFromLabelNames;
exports.projectWorkflowLabelNames = projectWorkflowLabelNames;
exports.resolveWorkflowStateSyncLabelNames = resolveWorkflowStateSyncLabelNames;
exports.isWorkflowStateSyncNoop = isWorkflowStateSyncNoop;
exports.labelsMatch = labelsMatch;
exports.formatWorkflowLabelNames = formatWorkflowLabelNames;
exports.resolveNeedsHumanReasonLabelNames = resolveNeedsHumanReasonLabelNames;
exports.resolveAuxiliaryManagedLabelNames = resolveAuxiliaryManagedLabelNames;
exports.pickAuxiliaryManagedLabelNames = pickAuxiliaryManagedLabelNames;
const catalog_1 = require("../../i18n/catalog");
const types_1 = require("../workflow-state/types");
exports.DEFAULT_WORKFLOW_LABELS = {
    aiReady: "AI: Ready",
    aiRunning: "AI: Running",
    aiNeedsHuman: "AI: Needs Human",
    aiWorkingInPr: "AI: Working in PR",
    aiDisabled: "AI: Disabled",
    aiRecurring: "AI: Recurring",
    aiScheduled: "AI: Scheduled",
    aiQuestion: "AI: Question",
    aiRunLimit: "AI: Run Limit",
    aiCoolingDown: "AI: Cooling Down",
    aiFollowUp: "AI: Follow-up",
};
exports.WORKFLOW_LABEL_KEYS = [
    "aiReady",
    "aiRunning",
    "aiNeedsHuman",
    "aiWorkingInPr",
    "aiDisabled",
    "aiRecurring",
    "aiScheduled",
    "aiQuestion",
    "aiRunLimit",
    "aiCoolingDown",
    "aiFollowUp",
];
const WORKFLOW_STATUS_LABEL_KEYS = {
    [types_1.WORKFLOW_STATUSES.aiReady]: "aiReady",
    [types_1.WORKFLOW_STATUSES.aiRunning]: "aiRunning",
    [types_1.WORKFLOW_STATUSES.aiNeedsHuman]: "aiNeedsHuman",
    [types_1.WORKFLOW_STATUSES.aiWorkingInPr]: "aiWorkingInPr",
    [types_1.WORKFLOW_STATUSES.aiRecurring]: "aiRecurring",
    [types_1.WORKFLOW_STATUSES.aiScheduled]: "aiScheduled",
};
const WORKFLOW_RULE_LABEL_KEYS = {
    [types_1.WORKFLOW_RULES.aiDisabled]: "aiDisabled",
};
const WORKFLOW_AUXILIARY_LABEL_KEYS = [
    "aiQuestion",
    "aiRunLimit",
    "aiCoolingDown",
];
const WORKFLOW_LABEL_DEFINITION_SPECS = [
    {
        labelKey: "aiReady",
        color: "0E8A16",
        descriptionKey: "ticketTracker.workflowLabel.aiReady",
    },
    {
        labelKey: "aiRunning",
        color: "0969DA",
        descriptionKey: "ticketTracker.workflowLabel.aiRunning",
    },
    {
        labelKey: "aiNeedsHuman",
        color: "D93F0B",
        descriptionKey: "ticketTracker.workflowLabel.aiNeedsHuman",
    },
    {
        labelKey: "aiWorkingInPr",
        color: "8250DF",
        descriptionKey: "ticketTracker.workflowLabel.aiWorkingInPr",
    },
    {
        labelKey: "aiDisabled",
        color: "AFB8C1",
        descriptionKey: "ticketTracker.workflowLabel.aiDisabled",
    },
    {
        labelKey: "aiRecurring",
        color: "0F8B8D",
        descriptionKey: "ticketTracker.workflowLabel.aiRecurring",
    },
    {
        labelKey: "aiScheduled",
        color: "BFD4F2",
        descriptionKey: "ticketTracker.workflowLabel.aiScheduled",
    },
    {
        labelKey: "aiQuestion",
        color: "54AEFF",
        descriptionKey: "ticketTracker.workflowLabel.aiQuestion",
    },
    {
        labelKey: "aiRunLimit",
        color: "B08800",
        descriptionKey: "ticketTracker.workflowLabel.aiRunLimit",
    },
    {
        labelKey: "aiCoolingDown",
        color: "D0D7DE",
        descriptionKey: "ticketTracker.workflowLabel.aiCoolingDown",
    },
];
const FOLLOWUP_LABEL_DEFINITION_SPEC = {
    labelKey: "aiFollowUp",
    color: "6F42C1",
    descriptionKey: "ticketTracker.workflowLabel.followupRequest",
};
function resolveWorkflowLabels(workflowLabels) {
    return {
        aiReady: workflowLabels.aiReady,
        aiRunning: workflowLabels.aiRunning,
        aiNeedsHuman: workflowLabels.aiNeedsHuman,
        aiWorkingInPr: workflowLabels.aiWorkingInPr ?? exports.DEFAULT_WORKFLOW_LABELS.aiWorkingInPr,
        aiDisabled: workflowLabels.aiDisabled,
        aiRecurring: workflowLabels.aiRecurring ?? exports.DEFAULT_WORKFLOW_LABELS.aiRecurring,
        aiScheduled: workflowLabels.aiScheduled ?? exports.DEFAULT_WORKFLOW_LABELS.aiScheduled,
        aiQuestion: workflowLabels.aiQuestion ?? exports.DEFAULT_WORKFLOW_LABELS.aiQuestion,
        aiRunLimit: workflowLabels.aiRunLimit ?? exports.DEFAULT_WORKFLOW_LABELS.aiRunLimit,
        aiCoolingDown: workflowLabels.aiCoolingDown ?? exports.DEFAULT_WORKFLOW_LABELS.aiCoolingDown,
        aiFollowUp: workflowLabels.aiFollowUp ?? exports.DEFAULT_WORKFLOW_LABELS.aiFollowUp,
    };
}
function buildWorkflowLabelDefinitions(workflowLabels, locale) {
    const resolvedWorkflowLabels = resolveWorkflowLabels(workflowLabels);
    return WORKFLOW_LABEL_DEFINITION_SPECS.map((spec) => buildWorkflowLabelDefinition(resolvedWorkflowLabels, locale, spec));
}
function buildManagedLabelDefinitions(input) {
    const resolvedWorkflowLabels = resolveWorkflowLabels(input.workflowLabels);
    return [
        ...buildWorkflowLabelDefinitions(resolvedWorkflowLabels, input.locale),
        buildWorkflowLabelDefinition(resolvedWorkflowLabels, input.locale, FOLLOWUP_LABEL_DEFINITION_SPEC),
    ];
}
function getFollowupRequestLabelName(workflowLabels) {
    return resolveWorkflowLabels(workflowLabels).aiFollowUp;
}
function getNonFollowupManagedLabelNames(workflowLabels) {
    const { aiFollowUp: _aiFollowUp, ...labels } = resolveWorkflowLabels(workflowLabels);
    return Object.values(labels);
}
function getAuxiliaryManagedLabelNames(workflowLabels) {
    const resolvedLabels = resolveWorkflowLabels(workflowLabels);
    return WORKFLOW_AUXILIARY_LABEL_KEYS.map((key) => resolvedLabels[key]);
}
function diffWorkflowLabelDefinitions(requiredLabels, currentLabels) {
    const currentLabelByName = new Map(currentLabels.map((label) => [label.name, label]));
    const missing = [];
    const mismatched = [];
    for (const requiredLabel of requiredLabels) {
        const currentLabel = currentLabelByName.get(requiredLabel.name);
        if (!currentLabel) {
            missing.push(requiredLabel);
            continue;
        }
        if (!workflowLabelDefinitionsMatch(requiredLabel, currentLabel)) {
            mismatched.push(requiredLabel);
        }
    }
    return { missing, mismatched };
}
function getWorkflowLabelForStatus(workflowLabels, status) {
    const resolvedLabels = resolveWorkflowLabels(workflowLabels);
    return resolvedLabels[WORKFLOW_STATUS_LABEL_KEYS[status]];
}
function getWorkflowLabelForRule(workflowLabels, rule) {
    const resolvedLabels = resolveWorkflowLabels(workflowLabels);
    return resolvedLabels[WORKFLOW_RULE_LABEL_KEYS[rule]];
}
function parseWorkflowStateFromLabelNames(workflowLabels, labelNames) {
    const resolvedLabels = resolveWorkflowLabels(workflowLabels);
    const managed = labelNames.filter((label) => isManagedWorkflowLabel(label, resolvedLabels));
    if (managed.length === 0) {
        return null;
    }
    const statuses = managed.filter((label) => isManagedWorkflowStatusLabel(label, resolvedLabels));
    const rules = managed.filter((label) => isManagedWorkflowRuleLabel(label, resolvedLabels));
    const status = resolveParsedWorkflowStatus(statuses, resolvedLabels);
    if (status !== null && statuses.length + rules.length === managed.length) {
        return {
            status,
            rules: rules.flatMap((label) => {
                const rule = getWorkflowRuleByLabel(label, resolvedLabels);
                return rule === undefined ? [] : [rule];
            }),
        };
    }
    if (status === null &&
        managed.length === 1 &&
        statuses.length === 0 &&
        rules.length === 1 &&
        rules[0] ===
            resolvedLabels[WORKFLOW_RULE_LABEL_KEYS[types_1.WORKFLOW_RULES.aiDisabled]]) {
        return {
            status: types_1.WORKFLOW_STATUSES.aiReady,
            rules: [types_1.WORKFLOW_RULES.aiDisabled],
        };
    }
    return null;
}
function projectWorkflowLabelNames(workflowLabels, snapshot, options = {}) {
    if (options.omitWorkflowLabels) {
        return [];
    }
    const labels = [];
    if (!(options.omitReadyStatusLabel &&
        snapshot.status === types_1.WORKFLOW_STATUSES.aiReady)) {
        labels.push(getWorkflowLabelForStatus(workflowLabels, snapshot.status));
    }
    labels.push(...snapshot.rules.map((rule) => getWorkflowLabelForRule(workflowLabels, rule)));
    return labels;
}
function resolveWorkflowStateSyncLabelNames(input) {
    const managedLabels = new Set([
        ...getManagedWorkflowStatusAndRuleLabelNames(input.workflowLabels),
        ...(input.auxiliaryManagedLabels?.previous ?? []),
        ...(input.auxiliaryManagedLabels?.next ?? []),
    ]);
    const currentNonManagedLabels = input.currentLabelNames.filter((label) => !managedLabels.has(label));
    return dedupeTextValues([
        ...currentNonManagedLabels,
        ...projectWorkflowLabelNames(input.workflowLabels, input.next, input.labelProjection),
        ...(input.auxiliaryManagedLabels?.next ?? []),
    ]);
}
function isWorkflowStateSyncNoop(input) {
    return labelsMatch(input.currentLabelNames, resolveWorkflowStateSyncLabelNames(input));
}
function labelsMatch(previous, next) {
    if (previous.length !== next.length) {
        return false;
    }
    return previous.every((label, index) => label === next[index]);
}
function getManagedWorkflowStatusAndRuleLabelNames(workflowLabels) {
    const resolvedLabels = resolveWorkflowLabels(workflowLabels);
    return [
        ...getWorkflowStatusLabelEntries(resolvedLabels).map((entry) => entry.label),
        ...getWorkflowRuleLabelEntries(resolvedLabels).map((entry) => entry.label),
    ];
}
function formatWorkflowLabelNames(workflowLabels, snapshot) {
    return projectWorkflowLabelNames(workflowLabels, snapshot).join(", ");
}
function resolveNeedsHumanReasonLabelNames(workflowLabels, reason) {
    const resolvedLabels = resolveWorkflowLabels(workflowLabels);
    if (reason === null) {
        return [];
    }
    switch (reason) {
        case "question":
            return [resolvedLabels.aiQuestion];
        case "run_limit":
            return [resolvedLabels.aiRunLimit];
        case "assignee_resolution":
        case "foreign_approval":
        case "start_approval":
            return [];
        default:
            return [];
    }
}
function resolveAuxiliaryManagedLabelNames(input) {
    const labels = [];
    const resolvedLabels = resolveWorkflowLabels(input.workflowLabels);
    if (input.snapshot.status === types_1.WORKFLOW_STATUSES.aiNeedsHuman) {
        labels.push(...resolveNeedsHumanReasonLabelNames(input.workflowLabels, input.needsHumanReason ?? null));
    }
    if (input.coolingDown === true) {
        labels.push(resolvedLabels.aiCoolingDown);
    }
    if (input.snapshot.status !== types_1.WORKFLOW_STATUSES.aiRecurring) {
        labels.push(...(input.recurringLabelNames ?? []));
    }
    return [...new Set(labels)];
}
function isManagedWorkflowLabel(label, workflowLabels) {
    return (isManagedWorkflowStatusLabel(label, workflowLabels) ||
        isManagedWorkflowRuleLabel(label, workflowLabels));
}
function isManagedWorkflowStatusLabel(label, workflowLabels) {
    return getWorkflowStatusLabelEntries(workflowLabels).some((entry) => entry.label === label);
}
function isManagedWorkflowRuleLabel(label, workflowLabels) {
    return getWorkflowRuleLabelEntries(workflowLabels).some((entry) => entry.label === label);
}
function resolveParsedWorkflowStatus(statuses, workflowLabels) {
    const primaryStatuses = statuses.filter((status) => status !== workflowLabels.aiRecurring);
    const hasRecurringStatus = primaryStatuses.length !== statuses.length;
    if (primaryStatuses.length === 0) {
        return hasRecurringStatus ? types_1.WORKFLOW_STATUSES.aiRecurring : null;
    }
    if (primaryStatuses.length === 1) {
        const primaryStatus = primaryStatuses[0];
        return primaryStatus === undefined
            ? null
            : (getWorkflowStatusByLabel(primaryStatus, workflowLabels) ?? null);
    }
    if (primaryStatuses.length === 2 &&
        primaryStatuses.includes(workflowLabels.aiReady) &&
        primaryStatuses.includes(workflowLabels.aiNeedsHuman)) {
        return types_1.WORKFLOW_STATUSES.aiReady;
    }
    return null;
}
function buildWorkflowLabelDefinition(workflowLabels, locale, spec) {
    return {
        name: workflowLabels[spec.labelKey],
        color: spec.color,
        description: (0, catalog_1.translate)(locale, spec.descriptionKey),
    };
}
function getWorkflowStatusLabelEntries(workflowLabels) {
    return Object.entries(WORKFLOW_STATUS_LABEL_KEYS).map(([status, labelKey]) => ({
        status: status,
        label: workflowLabels[labelKey],
    }));
}
function getWorkflowRuleLabelEntries(workflowLabels) {
    return Object.entries(WORKFLOW_RULE_LABEL_KEYS).map(([rule, labelKey]) => ({
        rule: rule,
        label: workflowLabels[labelKey],
    }));
}
function getWorkflowStatusByLabel(label, workflowLabels) {
    return getWorkflowStatusLabelEntries(workflowLabels).find((entry) => entry.label === label)?.status;
}
function getWorkflowRuleByLabel(label, workflowLabels) {
    return getWorkflowRuleLabelEntries(workflowLabels).find((entry) => entry.label === label)?.rule;
}
function pickAuxiliaryManagedLabelNames(workflowLabels, labelNames) {
    if (!labelNames) {
        return [];
    }
    const labels = new Set(labelNames);
    return getAuxiliaryManagedLabelNames(workflowLabels).filter((label) => labels.has(label));
}
function dedupeTextValues(values) {
    return [...new Set(values)];
}
function workflowLabelDefinitionsMatch(requiredLabel, currentLabel) {
    return (normalizeWorkflowLabelColor(requiredLabel.color) ===
        normalizeWorkflowLabelColor(currentLabel.color) &&
        normalizeWorkflowLabelDescription(requiredLabel.description) ===
            normalizeWorkflowLabelDescription(currentLabel.description));
}
function normalizeWorkflowLabelColor(color) {
    return color?.replace(/^#/, "").trim().toLowerCase() ?? "";
}
function normalizeWorkflowLabelDescription(description) {
    return description?.trim() ?? "";
}
