"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.resolveWorkflowScanState = resolveWorkflowScanState;
exports.resolveCommandlessWorkflowScanDecision = resolveCommandlessWorkflowScanDecision;
exports.isPotentialWorkflowSetupIssueCandidate = isPotentialWorkflowSetupIssueCandidate;
exports.resolveRunnableWorkflowSetupRequest = resolveRunnableWorkflowSetupRequest;
exports.resolveRunnableWorkflowSetupRequestForIssue = resolveRunnableWorkflowSetupRequestForIssue;
exports.resolveFreshActionableComment = resolveFreshActionableComment;
const canonical_workflow_state_1 = require("../../comments/canonical-workflow-state");
const control_plane_config_1 = require("../../config/control-plane-config");
const followup_request_body_1 = require("../../issues/followup-request-body");
const types_1 = require("../../platform/ticket-tracker/types");
const types_2 = require("../../platform/workflow-state/types");
const shared_1 = require("../../run/run-once-cycle/shared");
const execution_ownership_1 = require("../../run/execution-ownership");
const preflight_resolution_marker_1 = require("../../run/run-once-cycle/preflight-resolution-marker");
const foreign_input_approval_1 = require("../../workflows/foreign-input-approval");
const assignee_resolution_1 = require("../../workflows/assignee-resolution");
const publisher_events_1 = require("../../workflows/publisher-events");
const replan_comment_1 = require("../../workflows/replan-comment");
const state_1 = require("../../workflows/state");
const workflow_command_state_1 = require("../../workflows/workflow-command-state");
const workflow_timeline_scan_1 = require("../../workflows/workflow-timeline-scan");
const start_approval_support_1 = require("../../workflows/start-approval-support");
const recurring_1 = require("../../workflows/recurring");
const scheduled_run_1 = require("../../workflows/scheduled-run");
async function resolveWorkflowScanState(input) {
    const comments = await (0, shared_1.loadSortedIssueComments)(input.ticketTracker, input.issue.id, {
        timeline: "issue-only",
    });
    const canonicalResolution = (0, canonical_workflow_state_1.resolveCanonicalWorkflowStateComment)(comments, input.responseLanguage);
    const stickyState = canonicalResolution.kind === "found"
        ? canonicalResolution.workflowState
        : null;
    const scan = (0, workflow_timeline_scan_1.scanWorkflowTimeline)({
        comments,
        issueBody: input.issue.kind === types_1.TRACKER_ITEM_KINDS.issue ? input.issue.body : null,
        workflowState: stickyState,
    });
    const commandDecision = resolveLatestCommandDecision(scan);
    return {
        comments,
        scan,
        commandDecision,
        stickyState,
        canonicalWorkflowStateError: canonicalResolution.kind === "invalid"
            ? {
                comment: canonicalResolution.comment,
                summary: canonicalResolution.summary,
            }
            : null,
        currentWorkflowStateCommentId: canonicalResolution.kind === "found"
            ? canonicalResolution.comment.id
            : null,
        scannedInputCursor: scan.scannedInputCursor,
        currentNeedsHumanReason: (0, types_1.hasTrackerWorkflowState)(input.issue) &&
            input.issue.workflowState.status === types_2.WORKFLOW_STATUSES.aiNeedsHuman
            ? (stickyState?.needsHumanReason ?? null)
            : null,
        responseLanguage: input.responseLanguage,
    };
}
function resolveLatestCommandDecision(scan) {
    const workflowCommand = (0, workflow_command_state_1.resolvePendingWorkflowCommandFromEvents)(scan.workflowCommandEvents);
    const operationalCommand = resolveLatestEffectiveOperationalCommand(scan.commentsAfterCursor);
    if (workflowCommand === null && operationalCommand === null) {
        return { kind: "none" };
    }
    if (workflowCommand === null && operationalCommand !== null) {
        return operationalCommand.kind === "approve"
            ? {
                kind: "approve",
                comment: operationalCommand.comment,
            }
            : {
                kind: "start",
                comment: operationalCommand.comment,
            };
    }
    if (workflowCommand === null) {
        return { kind: "none" };
    }
    if (operationalCommand !== null) {
        if (workflowCommand.source === "body") {
            return operationalCommand.kind === "approve"
                ? {
                    kind: "approve",
                    comment: operationalCommand.comment,
                }
                : {
                    kind: "start",
                    comment: operationalCommand.comment,
                };
        }
        const workflowIndex = scan.commentsAfterCursor.findIndex((comment) => comment.id === workflowCommand.comment.id);
        const operationalIndex = scan.commentsAfterCursor.findIndex((comment) => comment.id === operationalCommand.comment.id);
        if (operationalIndex > workflowIndex) {
            return operationalCommand.kind === "approve"
                ? {
                    kind: "approve",
                    comment: operationalCommand.comment,
                }
                : {
                    kind: "start",
                    comment: operationalCommand.comment,
                };
        }
    }
    return {
        kind: "workflow_command",
        command: workflowCommand,
    };
}
function resolveLatestEffectiveOperationalCommand(comments) {
    for (const comment of [...comments].reverse()) {
        const classification = (0, workflow_timeline_scan_1.classifyWorkflowTimelineComment)(comment);
        if (classification === "managed") {
            continue;
        }
        if (classification === "approve_command") {
            return {
                kind: "approve",
                comment,
            };
        }
        if (classification === "start_command") {
            return {
                kind: "start",
                comment,
            };
        }
        return null;
    }
    return null;
}
async function resolveCommandlessWorkflowScanDecision(input) {
    const assigneeResolutionDecision = await resolveCommandlessAssigneeResolutionDecision(input);
    if (assigneeResolutionDecision !== null) {
        return assigneeResolutionDecision;
    }
    const foreignApprovalDecision = await resolveCommandlessForeignApprovalDecision(input);
    if (foreignApprovalDecision !== null) {
        return foreignApprovalDecision;
    }
    return resolveBaseCommandlessWorkflowScanDecision(input);
}
async function resolveCommandlessAssigneeResolutionDecision(input) {
    if (input.issue.workflowState.rules.includes(types_2.WORKFLOW_RULES.aiDisabled)) {
        return null;
    }
    const assigneeGate = (0, assignee_resolution_1.resolveWorkflowAssigneeGate)({
        assignees: input.issue.assignees,
    });
    const currentNeedsHumanReason = input.currentNeedsHumanReason ?? null;
    const approvalRequirement = await (0, foreign_input_approval_1.resolveForeignApprovalRequirement)({
        ticketTracker: input.ticketTracker,
        config: input.config,
        issue: input.issue,
        comments: input.comments,
        scanStartCursor: input.scan.scanStartCursor,
        currentAssignee: input.currentAssignee,
        ...(input.stickyState?.foreignInputApproval !== undefined
            ? { approvalState: input.stickyState.foreignInputApproval }
            : {}),
    });
    const requiresForeignApproval = approvalRequirement.required;
    const hadStoredStartApproval = (0, state_1.hasPendingWorkflowStartApproval)(input.stickyState);
    const requiresStartApproval = !requiresForeignApproval && isStartApprovalWaitState(input);
    if (!requiresForeignApproval && !requiresStartApproval) {
        return currentNeedsHumanReason ===
            publisher_events_1.WORKFLOW_NEEDS_HUMAN_REASONS.assigneeResolution ||
            (currentNeedsHumanReason === publisher_events_1.WORKFLOW_NEEDS_HUMAN_REASONS.startApproval &&
                hadStoredStartApproval)
            ? { kind: "assignee_resolution_released_to_ready" }
            : null;
    }
    if (assigneeGate.kind !== "ok") {
        return {
            kind: "assignee_resolution_required",
            resolution: assigneeGate.kind,
        };
    }
    if (currentNeedsHumanReason !== publisher_events_1.WORKFLOW_NEEDS_HUMAN_REASONS.assigneeResolution) {
        return null;
    }
    if (requiresForeignApproval) {
        return {
            kind: "foreign_approval_required",
            comment: approvalRequirement.triggerComment ?? null,
        };
    }
    return { kind: "assignee_resolution_released_to_start_approval" };
}
function resolveBaseCommandlessWorkflowScanDecision(input) {
    const freshActionableComment = resolveFreshActionableComment(input);
    if (freshActionableComment !== null &&
        shouldQueueStartApprovalPlanningPassFromComment({
            config: input.config,
            issue: input.issue,
            stickyState: input.stickyState,
        })) {
        return {
            kind: "revise_plan_feedback",
            comment: freshActionableComment,
        };
    }
    if (freshActionableComment !== null &&
        shouldResumeNeedsHumanIssueFromComment({
            config: input.config,
            issue: input.issue,
            stickyState: input.stickyState,
        })) {
        return {
            kind: "resume_from_human_input",
        };
    }
    if (input.enableImplicitReplan) {
        const replan = resolveImplicitReplanRequest({
            scan: input.scan,
            issue: input.issue,
            stickyState: input.stickyState,
            responseLanguage: input.responseLanguage,
        });
        if (replan !== null) {
            return {
                kind: "implicit_replan",
                comment: replan.comment,
                reason: replan.reason,
            };
        }
    }
    return { kind: "recurring_projection_sync" };
}
function isWorkflowSetupIssueCandidate(issue, stickyState) {
    if (!(issue.kind === types_1.TRACKER_ITEM_KINDS.issue &&
        issue.isOpen &&
        !issue.workflowState.rules.includes(types_2.WORKFLOW_RULES.aiDisabled))) {
        return false;
    }
    return issue.workflowState.status === types_2.WORKFLOW_STATUSES.aiReady
        ? true
        : issue.workflowState.status === types_2.WORKFLOW_STATUSES.aiRecurring &&
            (0, recurring_1.isRecurringParentWorkflowState)(stickyState);
}
function isPotentialWorkflowSetupIssueCandidate(issue) {
    return (issue.kind === types_1.TRACKER_ITEM_KINDS.issue &&
        issue.isOpen &&
        (issue.workflowState.status === types_2.WORKFLOW_STATUSES.aiReady ||
            issue.workflowState.status === types_2.WORKFLOW_STATUSES.aiRecurring) &&
        !issue.workflowState.rules.includes(types_2.WORKFLOW_RULES.aiDisabled));
}
function resolveWorkflowSetupRequest(input) {
    if (!isWorkflowSetupIssueCandidate(input.issue, input.stickyState)) {
        return null;
    }
    if ((0, preflight_resolution_marker_1.isPreflightResolutionIssue)(input.issue)) {
        return null;
    }
    if (input.stickyState === null) {
        const text = input.issue.body.trim();
        return input.issue.workflowState.status === types_2.WORKFLOW_STATUSES.aiReady &&
            text.length > 0
            ? {
                kind: "tracker_issue_body",
                text,
                cursor: null,
            }
            : null;
    }
    if (input.aiWorkflowOptionAutofill === "off") {
        return null;
    }
    if (input.freshActionableComment !== null) {
        const text = input.freshActionableComment.body.trim();
        return text.length === 0
            ? null
            : {
                kind: "fresh_comment",
                text,
                comment: input.freshActionableComment,
                cursor: (0, workflow_timeline_scan_1.toWorkflowCommentCursor)(input.freshActionableComment),
            };
    }
    const followupIssueBodyText = resolveInitialFollowupIssueBodySetupText({
        issue: input.issue,
        stickyState: input.stickyState,
    });
    if (followupIssueBodyText !== null) {
        return {
            kind: "tracker_issue_body",
            text: followupIssueBodyText,
            cursor: null,
        };
    }
    return null;
}
function resolveInitialFollowupIssueBodySetupText(input) {
    if (input.issue.workflowState.status !== types_2.WORKFLOW_STATUSES.aiReady ||
        input.stickyState.workflowSurface !== "followup" ||
        input.stickyState.plan !== null ||
        (0, scheduled_run_1.hasActiveScheduledRun)(input.stickyState) ||
        (0, recurring_1.isRecurringParentWorkflowState)(input.stickyState)) {
        return null;
    }
    const text = (0, followup_request_body_1.extractFollowupRequestSectionText)(input.issue.body);
    if (text === null || (0, followup_request_body_1.isDefaultFollowupRequestText)(text)) {
        return null;
    }
    return text;
}
async function resolveRunnableWorkflowSetupRequest(input) {
    if (input.scanState.canonicalWorkflowStateError !== null ||
        input.scanState.commandDecision.kind !== "none" ||
        (0, execution_ownership_1.isExecutionOwnershipActive)(input.scanState.stickyState?.executionOwnership)) {
        return null;
    }
    const effectiveConfig = (0, control_plane_config_1.resolveIssueEffectiveConfigForWorkflowState)(input.config, input.scanState.stickyState);
    const assigneeDecision = await resolveCommandlessAssigneeResolutionDecision({
        ticketTracker: input.ticketTracker,
        config: effectiveConfig,
        comments: input.scanState.comments,
        scan: input.scanState.scan,
        issue: input.issue,
        stickyState: input.scanState.stickyState,
        currentAssignee: input.currentAssignee ?? resolveSingleIssueAssignee(input.issue),
        currentNeedsHumanReason: input.scanState.currentNeedsHumanReason,
    });
    if (assigneeDecision !== null) {
        return null;
    }
    const foreignApprovalDecision = await resolveCommandlessForeignApprovalDecision({
        ticketTracker: input.ticketTracker,
        config: effectiveConfig,
        comments: input.scanState.comments,
        scan: input.scanState.scan,
        issue: input.issue,
        stickyState: input.scanState.stickyState,
        currentAssignee: input.currentAssignee ?? resolveSingleIssueAssignee(input.issue),
    });
    if (foreignApprovalDecision !== null) {
        return null;
    }
    return resolveWorkflowSetupRequest({
        issue: input.issue,
        stickyState: input.scanState.stickyState,
        freshActionableComment: resolveFreshActionableComment({
            scan: input.scanState.scan,
            stickyState: input.scanState.stickyState,
        }),
        aiWorkflowOptionAutofill: effectiveConfig.aiWorkflowOptionAutofill,
    });
}
async function resolveRunnableWorkflowSetupRequestForIssue(input) {
    const scanState = await resolveWorkflowScanState({
        ticketTracker: input.ticketTracker,
        issue: input.issue,
        responseLanguage: input.responseLanguage,
    });
    return resolveRunnableWorkflowSetupRequest({
        ticketTracker: input.ticketTracker,
        config: input.config,
        issue: input.issue,
        scanState,
        ...(input.currentAssignee !== undefined
            ? { currentAssignee: input.currentAssignee }
            : {}),
    });
}
function resolveSingleIssueAssignee(issue) {
    return issue.assignees.length === 1 ? (issue.assignees[0] ?? null) : null;
}
async function resolveCommandlessForeignApprovalDecision(input) {
    if (input.issue.workflowState.rules.includes(types_2.WORKFLOW_RULES.aiDisabled)) {
        return null;
    }
    const approvalRequirement = await (0, foreign_input_approval_1.resolveForeignApprovalRequirement)({
        ticketTracker: input.ticketTracker,
        config: input.config,
        issue: input.issue,
        comments: input.comments,
        scanStartCursor: input.scan.scanStartCursor,
        currentAssignee: input.currentAssignee,
        ...(input.stickyState?.foreignInputApproval !== undefined
            ? { approvalState: input.stickyState.foreignInputApproval }
            : {}),
    });
    if (!approvalRequirement.required) {
        return null;
    }
    if (input.issue.workflowState.status === types_2.WORKFLOW_STATUSES.aiNeedsHuman &&
        input.scan.latestActionableComment === null) {
        return null;
    }
    return {
        kind: "foreign_approval_required",
        comment: approvalRequirement.triggerComment,
    };
}
function resolveImplicitReplanRequest(input) {
    const freshActionableComment = resolveFreshActionableComment(input);
    if (input.stickyState === null || freshActionableComment === null) {
        return null;
    }
    if (input.issue.workflowState.status !== types_2.WORKFLOW_STATUSES.aiReady &&
        !isIssueReviewReadyNeedsHumanIssue(input)) {
        return null;
    }
    if (input.issue.workflowState.rules.includes(types_2.WORKFLOW_RULES.aiDisabled)) {
        return null;
    }
    return {
        comment: freshActionableComment,
        reason: (0, replan_comment_1.buildWorkflowReplanReason)({
            responseLanguage: input.responseLanguage,
            reason: freshActionableComment.body,
        }),
    };
}
function isIssueReviewReadyNeedsHumanIssue(input) {
    return (input.issue.kind === types_1.TRACKER_ITEM_KINDS.issue &&
        input.issue.workflowState.status === types_2.WORKFLOW_STATUSES.aiNeedsHuman &&
        input.stickyState?.needsHumanReason ===
            publisher_events_1.WORKFLOW_NEEDS_HUMAN_REASONS.reviewReady);
}
function resolveFreshActionableComment(input) {
    if (input.stickyState === null) {
        return null;
    }
    return input.scan.latestActionableComment ?? null;
}
function shouldQueueStartApprovalPlanningPassFromComment(input) {
    return (input.stickyState !== null &&
        (0, start_approval_support_1.isWorkflowAwaitingActiveStartApproval)({
            config: input.config,
            issue: input.issue,
            workflowState: input.stickyState,
        }) &&
        input.issue.workflowState.status === types_2.WORKFLOW_STATUSES.aiNeedsHuman &&
        !input.issue.workflowState.rules.includes(types_2.WORKFLOW_RULES.aiDisabled));
}
function isStartApprovalWaitState(input) {
    return (input.stickyState !== null &&
        (0, start_approval_support_1.hasActiveWorkflowStartApproval)({
            config: input.config,
            issue: input.issue,
            workflowState: input.stickyState,
        }) &&
        input.issue.workflowState.status === types_2.WORKFLOW_STATUSES.aiNeedsHuman &&
        !input.issue.workflowState.rules.includes(types_2.WORKFLOW_RULES.aiDisabled));
}
function shouldResumeNeedsHumanIssueFromComment(input) {
    return (input.stickyState !== null &&
        input.issue.workflowState.status === types_2.WORKFLOW_STATUSES.aiNeedsHuman &&
        (0, state_1.isHumanInputResumeReason)(input.stickyState.needsHumanReason) &&
        !isIssueReviewReadyNeedsHumanIssue(input) &&
        !(0, start_approval_support_1.hasActiveWorkflowStartApproval)({
            config: input.config,
            issue: input.issue,
            workflowState: input.stickyState,
        }) &&
        !input.issue.workflowState.rules.includes(types_2.WORKFLOW_RULES.aiDisabled));
}
