"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.materializeServiceRuntimeConfigScanPlan = materializeServiceRuntimeConfigScanPlan;
const workflow_labels_1 = require("../../platform/ticket-tracker/workflow-labels");
const types_1 = require("../../platform/workflow-state/types");
const same_issue_replan_publication_1 = require("../../run/run-once-cycle/same-issue-replan-publication");
const publisher_1 = require("../../workflows/publisher");
const publish_request_builders_1 = require("../../workflows/publish-request-builders");
const publisher_state_support_1 = require("../../workflows/publisher-state-support");
const publish_target_support_1 = require("../../workflows/publish-target-support");
const config_scan_plan_1 = require("./config-scan-plan");
function materializeServiceRuntimeConfigScanPlan(input) {
    if (input.planSpec.kind === "noop") {
        return (0, config_scan_plan_1.buildServiceRuntimeNoopPlan)(input.planSpec.decisionKind, input.planSpec.targetIssueId);
    }
    if (input.planSpec.kind === "same_issue_replan") {
        return materializeSameIssueReplanPlan({
            planSpec: input.planSpec,
            issueComments: input.issueComments,
            workflowLabels: input.workflowLabels,
        });
    }
    return materializePublishSpecPlan({
        planSpec: input.planSpec,
        issueComments: input.issueComments,
        workflowLabels: input.workflowLabels,
    });
}
function resolveServiceRuntimeCommentCursorPolicy(input) {
    if (input.mode === publisher_1.WORKFLOW_COMMENT_CURSOR_POLICY_MODES.preserve) {
        return { mode: publisher_1.WORKFLOW_COMMENT_CURSOR_POLICY_MODES.preserve };
    }
    const mode = input.mode ??
        (input.visibleUpdate === undefined
            ? publisher_1.WORKFLOW_COMMENT_CURSOR_POLICY_MODES.advanceToScannedInput
            : publisher_1.WORKFLOW_COMMENT_CURSOR_POLICY_MODES.advanceToPublishedCommentIfSafe);
    return {
        mode,
        scannedInputCursor: input.cursor,
    };
}
function resolveServiceWorkflowProjection(input) {
    if (input.workflowProjection === undefined) {
        return undefined;
    }
    return isServiceWorkflowProjectionNoop({
        issue: input.issue,
        workflowLabels: input.workflowLabels,
        workflowProjection: input.workflowProjection,
    })
        ? undefined
        : input.workflowProjection;
}
function materializeSameIssueReplanPlan(input) {
    const request = (0, same_issue_replan_publication_1.buildSameIssueReplanPublishRequest)({
        intent: input.planSpec.intent,
        issueComments: input.issueComments,
        workflowLabels: input.workflowLabels,
        responseLanguage: input.planSpec.responseLanguage,
    });
    if (request === null) {
        return (0, config_scan_plan_1.buildServiceRuntimeNoopPlan)(input.planSpec.decisionKind, input.planSpec.intent.issue.id);
    }
    return {
        kind: "publish",
        decisionKind: input.planSpec.decisionKind,
        targetIssueId: input.planSpec.intent.issue.id,
        publish: {
            request,
        },
    };
}
function materializePublishSpecPlan(input) {
    const workflowProjection = resolveServiceWorkflowProjection({
        issue: input.planSpec.issue,
        workflowLabels: input.workflowLabels,
        workflowProjection: input.planSpec.workflowProjection,
    });
    if (input.planSpec.forcePublish !== true &&
        workflowProjection === undefined &&
        input.planSpec.visibleUpdate === undefined &&
        input.planSpec.scannedInputCursor === null) {
        return (0, config_scan_plan_1.buildServiceRuntimeNoopPlan)(input.planSpec.decisionKind, input.planSpec.issue.id);
    }
    const target = (0, publish_target_support_1.resolveLinkedIssuePublishTarget)({
        issue: input.planSpec.issue,
        comments: input.issueComments,
        unlinkedPullRequestPolicy: input.planSpec.workflowState !== null || workflowProjection !== undefined
            ? "null"
            : "existing_issue",
    });
    if (target === null || target.kind === "new_issue") {
        return (0, config_scan_plan_1.buildServiceRuntimeNoopPlan)(input.planSpec.decisionKind, input.planSpec.issue.id);
    }
    return {
        kind: "publish",
        decisionKind: input.planSpec.decisionKind,
        targetIssueId: input.planSpec.issue.id,
        publish: {
            request: buildServiceRuntimeWorkflowPublishRequest({
                target,
                workflowState: input.planSpec.workflowState,
                commentCursorPolicy: resolveServiceRuntimeCommentCursorPolicy({
                    mode: input.planSpec.commentCursorPolicyMode,
                    cursor: input.planSpec.scannedInputCursor,
                    visibleUpdate: input.planSpec.visibleUpdate,
                }),
                responseLanguage: input.planSpec.responseLanguage,
                issueId: input.planSpec.issue.id,
                workflowProjection,
                visibleUpdate: input.planSpec.visibleUpdate,
                visibleUpdateDedupeCursor: input.planSpec.visibleUpdateDedupeCursor,
                publishPrecondition: input.planSpec.publishPrecondition,
                invalidWorkflowStatePolicy: input.planSpec.invalidWorkflowStatePolicy,
                appendCanonicalWorkflowStateComment: input.planSpec.appendCanonicalWorkflowStateComment,
            }),
        },
    };
}
function buildServiceRuntimeWorkflowPublishRequest(input) {
    const optionalFields = buildOptionalServiceRuntimePublishRequestFields(input);
    const workflowProjection = input.workflowProjection === undefined
        ? undefined
        : (0, publisher_state_support_1.buildWorkflowProjectionChange)({
            issueId: input.issueId,
            previous: input.workflowProjection.previous,
            next: input.workflowProjection.next,
            labelProjection: input.workflowProjection.labelProjection,
            auxiliaryManagedLabels: input.workflowProjection.auxiliaryManagedLabels,
        });
    if (input.target.kind === "existing_issue") {
        return (0, publish_request_builders_1.buildExistingIssueWorkflowPublishRequest)({
            issueId: input.target.issueId,
            preloadedIssue: input.target.preloadedIssue,
            workflowState: input.workflowState,
            workflowProjection,
            commentCursorPolicy: input.commentCursorPolicy,
            responseLanguage: input.responseLanguage,
            ...optionalFields,
        });
    }
    return (0, publish_request_builders_1.buildPullRequestThreadWorkflowPublishRequest)({
        pullRequestThreadId: input.target.pullRequestThreadId,
        sourceIssueId: input.target.sourceIssueId,
        preloadedIssue: input.target.preloadedIssue,
        workflowState: input.workflowState,
        workflowProjection,
        commentCursorPolicy: input.commentCursorPolicy,
        responseLanguage: input.responseLanguage,
        ...optionalFields,
    });
}
function buildOptionalServiceRuntimePublishRequestFields(input) {
    const fields = {};
    if (input.visibleUpdate !== undefined) {
        fields.visibleUpdate = input.visibleUpdate;
    }
    if (input.visibleUpdateDedupeCursor !== undefined) {
        fields.visibleUpdateDedupeCursor = input.visibleUpdateDedupeCursor;
    }
    if (input.publishPrecondition !== undefined) {
        fields.publishPrecondition = input.publishPrecondition;
    }
    if (input.invalidWorkflowStatePolicy !== undefined) {
        fields.invalidWorkflowStatePolicy = input.invalidWorkflowStatePolicy;
    }
    if (input.appendCanonicalWorkflowStateComment !== undefined) {
        fields.appendCanonicalWorkflowStateComment =
            input.appendCanonicalWorkflowStateComment;
    }
    return fields;
}
function isServiceWorkflowProjectionNoop(input) {
    const projection = input.workflowProjection;
    if (!(0, types_1.isSameWorkflowStateSnapshot)(projection.previous, projection.next)) {
        return false;
    }
    if (!areStringArraysEqual(projection.auxiliaryManagedLabels?.previous ?? [], projection.auxiliaryManagedLabels?.next ?? [])) {
        return false;
    }
    if (projection.labelProjection === undefined) {
        return true;
    }
    if (input.workflowLabels === undefined) {
        return true;
    }
    const currentLabelNames = input.issue.labelNames ?? [];
    const workflowLabelNames = new Set((0, workflow_labels_1.getNonFollowupManagedLabelNames)(input.workflowLabels));
    if (projection.labelProjection.omitWorkflowLabels === true &&
        currentLabelNames.some((label) => workflowLabelNames.has(label))) {
        return false;
    }
    if (projection.labelProjection.omitReadyStatusLabel === true &&
        input.issue.workflowState.status === types_1.WORKFLOW_STATUSES.aiReady) {
        return false;
    }
    return true;
}
function areStringArraysEqual(left, right) {
    if (left.length !== right.length) {
        return false;
    }
    return left.every((value, index) => value === right[index]);
}
