"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.resolvePreflightResolutionIssue = resolvePreflightResolutionIssue;
const resolution_issue_1 = require("../../mcp/resolution-issue");
const catalog_1 = require("../../i18n/catalog");
const types_1 = require("../../platform/workflow-state/types");
const resolution_issue_2 = require("../../skills/resolution-issue");
const publish_request_builders_1 = require("../../workflows/publish-request-builders");
const publisher_shared_1 = require("../../workflows/publisher-shared");
const state_1 = require("../../workflows/state");
const template_bindings_1 = require("../../workflows/template-bindings");
const template_registry_1 = require("../../workflows/template-registry");
const constants_1 = require("../constants");
const execution_ownership_1 = require("../execution-ownership");
const log_text_1 = require("../log-text");
const issue_branch_target_1 = require("./issue-branch-target");
const issue_creation_publication_1 = require("./issue-creation-publication");
const publisher_factory_1 = require("./publisher-factory");
const results_1 = require("./results");
const workflow_template_root_1 = require("./workflow-template-root");
const preflight_resolution_marker_1 = require("./preflight-resolution-marker");
const WORKFLOW_MAINTENANCE_TEMPLATE_PATH = "__system/workflow-maintenance.md";
async function resolvePreflightResolutionIssue(input) {
    const responseLanguage = input.issueContext.config.i18n.defaultLanguage;
    const parentIssue = input.preparation.latestIssue;
    const resolution = input.preparation.resolution;
    const initialResolution = await resolveMatchingPreflightResolutionIssues({
        issueContext: input.issueContext,
        parentIssueId: parentIssue.id,
        resolutionKind: resolution.resolutionKind,
        resolutionKey: resolution.resolutionKey,
    });
    const existingChild = initialResolution.openWinner;
    const publisher = (0, publisher_factory_1.createRunWorkflowPublisher)(input.issueContext);
    const workflowTemplateRepoRoot = (0, workflow_template_root_1.getWorkflowTemplateRepoRoot)(input.issueContext);
    const workflowTemplateCatalog = await (0, template_registry_1.loadWorkflowTemplates)((0, template_registry_1.getWorkflowTemplatesDirectoryPath)(workflowTemplateRepoRoot), responseLanguage);
    const childWorkflowState = buildPreflightResolutionWorkflowState({
        issueContext: input.issueContext,
        parentWorkflowState: input.preparation.workflowState,
        objective: resolution.title,
        resolutionKind: resolution.resolutionKind,
        workflowTemplateCatalog,
    });
    const trackerFields = buildPreflightResolutionTrackerFields(input.issueContext, parentIssue);
    const publication = await (0, issue_creation_publication_1.executeIssuePublicationPlans)({
        publisher,
        plans: [
            buildPreflightResolutionPublicationPlan({
                existingChild,
                parentIssue,
                resolution,
                trackerFields,
                childWorkflowState,
                responseLanguage,
            }),
        ],
        eventHooks: {
            repoRoot: workflowTemplateRepoRoot,
            config: input.issueContext.config,
            worker: input.issueContext.worker,
            ...(input.issueContext.logHomeDirectory !== undefined
                ? { homeDirectory: input.issueContext.logHomeDirectory }
                : {}),
        },
    });
    const childIssue = publication.executions[0]?.issue;
    if (childIssue === undefined) {
        throw new Error("Preflight resolution publication returned no child issue.");
    }
    const finalResolution = await resolveMatchingPreflightResolutionIssues({
        issueContext: input.issueContext,
        parentIssueId: parentIssue.id,
        resolutionKind: resolution.resolutionKind,
        resolutionKey: resolution.resolutionKey,
    });
    const canonicalChild = finalResolution.openWinner ?? childIssue;
    await closeDuplicatePreflightResolutionIssues({
        publisher,
        duplicates: finalResolution.openDuplicates,
        parentIssueId: parentIssue.id,
        winner: canonicalChild,
        responseLanguage,
    });
    const parentWorkflowProjection = buildPreflightParentWorkflowProjection({
        parentIssue,
        workflowState: input.preparation.workflowState,
    });
    const parentPublication = await publisher.publishWorkflow((0, publish_request_builders_1.buildExistingIssueWorkflowPublishRequest)({
        issueId: parentIssue.id,
        preloadedIssue: parentIssue,
        workflowState: buildPreflightParentWorkflowState(input.preparation.workflowState),
        ...(parentWorkflowProjection !== undefined
            ? { workflowProjection: parentWorkflowProjection }
            : {}),
        dependencyChanges: [
            {
                kind: "add_blocking_dependency",
                issue: { kind: "target" },
                blockedBy: { kind: "issue", issueId: canonicalChild.id },
            },
        ],
        visibleUpdate: {
            kind: "feedback",
            summary: resolution.summary,
            next: (0, catalog_1.translate)(responseLanguage, "run.preflight.parentUpdate.blockedBy", {
                displayId: canonicalChild.displayId,
                next: resolution.next,
            }),
        },
        commentCursorPolicy: {
            mode: publisher_shared_1.WORKFLOW_COMMENT_CURSOR_POLICY_MODES.preserve,
        },
        responseLanguage,
    }));
    await input.logger.appendSection((0, log_text_1.issueLogSection)("preflightResolution"), [
        resolution.summary,
        `Child issue: ${canonicalChild.displayId} ${canonicalChild.url}`,
    ].join("\n"));
    return (0, results_1.buildRunCliSummary)({
        issue: parentIssue,
        outcome: constants_1.RUN_ISSUE_OUTCOMES.queuedAi,
        responseLanguage,
        summary: (0, catalog_1.translate)(responseLanguage, "run.preflight.cliSummary.createdOrReused", {
            displayId: canonicalChild.displayId,
        }),
        commentUrl: parentPublication.visibleUpdateComment?.url ?? null,
        prUrl: null,
        nextStep: (0, catalog_1.translate)(responseLanguage, "run.preflight.cliSummary.waiting", {
            displayId: canonicalChild.displayId,
            resolutionKind: resolution.resolutionKind,
            resolutionKey: resolution.resolutionKey,
        }),
    });
}
function buildPreflightResolutionPublicationPlan(input) {
    if (input.existingChild !== undefined) {
        return (0, issue_creation_publication_1.buildPatchIssuePublicationPlan)({
            issueKey: input.resolution.resolutionKey,
            issue: input.existingChild,
            title: input.resolution.title,
            body: input.resolution.body,
            trackerFields: input.trackerFields,
            workflowState: input.childWorkflowState,
            workflowProjection: buildPreflightResolutionWorkflowProjection(),
            responseLanguage: input.responseLanguage,
        });
    }
    return (0, issue_creation_publication_1.buildCreateIssuePublicationPlan)({
        issueKey: input.resolution.resolutionKey,
        source: "preflight",
        branchTarget: "effective_base_branch",
        relationship: {
            kind: "preflight_resolution",
            parentIssueId: input.parentIssue.id,
            resolutionKey: input.resolution.resolutionKey,
        },
        title: input.resolution.title,
        body: input.resolution.body,
        trackerFields: input.trackerFields,
        workflowState: input.childWorkflowState,
        workflowProjection: buildPreflightResolutionWorkflowProjection(),
        dependencyChanges: [
            {
                kind: "add_blocking_dependency",
                issue: { kind: "issue", issueId: input.parentIssue.id },
                blockedBy: { kind: "target" },
            },
        ],
        newIssueFailurePolicy: "close_created_internal_issue",
        responseLanguage: input.responseLanguage,
    });
}
async function resolveMatchingPreflightResolutionIssues(input) {
    const matchingIssues = (await input.issueContext.ticketTracker.listIssues({
        state: "all",
    })).filter((issue) => isMatchingPreflightResolutionIssue({
        issue,
        parentIssueId: input.parentIssueId,
        resolutionKind: input.resolutionKind,
        resolutionKey: input.resolutionKey,
    }));
    const openIssues = matchingIssues
        .filter((issue) => issue.isOpen)
        .sort(comparePreflightResolutionIssues);
    const [openWinner, ...openDuplicates] = openIssues;
    return { openWinner, openDuplicates };
}
async function closeDuplicatePreflightResolutionIssues(input) {
    for (const duplicate of input.duplicates) {
        const winnerText = `${input.winner.displayId} ${input.winner.url}`;
        await input.publisher.publishWorkflow((0, publish_request_builders_1.buildExistingIssueWorkflowPublishRequest)({
            issueId: duplicate.id,
            preloadedIssue: duplicate,
            workflowState: null,
            dependencyChanges: [
                {
                    kind: "remove_blocking_dependency",
                    issue: { kind: "issue", issueId: input.parentIssueId },
                    blockedBy: { kind: "issue", issueId: duplicate.id },
                },
            ],
            visibleUpdate: {
                kind: "feedback",
                summary: (0, catalog_1.translate)(input.responseLanguage, "run.preflight.duplicate.summary"),
                next: (0, catalog_1.translate)(input.responseLanguage, "run.preflight.duplicate.next", {
                    winner: winnerText,
                }),
            },
            terminalAction: {
                kind: "close",
                postCloseWorkflowProjection: {
                    previous: duplicate.workflowState,
                    next: duplicate.workflowState,
                    ...(duplicate.labelNames !== undefined
                        ? { currentLabelNames: duplicate.labelNames }
                        : {}),
                    labelProjection: { omitWorkflowLabels: true },
                },
            },
            commentCursorPolicy: {
                mode: publisher_shared_1.WORKFLOW_COMMENT_CURSOR_POLICY_MODES.preserve,
            },
            responseLanguage: input.responseLanguage,
        }));
    }
}
function comparePreflightResolutionIssues(left, right) {
    const leftNumber = Number(left.id);
    const rightNumber = Number(right.id);
    if (Number.isFinite(leftNumber) && Number.isFinite(rightNumber)) {
        const diff = leftNumber - rightNumber;
        if (diff !== 0) {
            return diff;
        }
    }
    return left.id.localeCompare(right.id);
}
function buildPreflightResolutionWorkflowProjection() {
    const ready = {
        status: types_1.WORKFLOW_STATUSES.aiReady,
        rules: [],
    };
    return {
        previous: ready,
        next: ready,
    };
}
function buildPreflightParentWorkflowState(workflowState) {
    return workflowState === null ? null : (0, execution_ownership_1.stripExecutionOwnership)(workflowState);
}
function buildPreflightParentWorkflowProjection(input) {
    if (input.parentIssue.workflowState.status === types_1.WORKFLOW_STATUSES.aiReady &&
        input.workflowState?.executionOwnership === undefined) {
        return undefined;
    }
    return {
        previous: input.parentIssue.workflowState,
        next: {
            status: types_1.WORKFLOW_STATUSES.aiReady,
            rules: [...input.parentIssue.workflowState.rules],
        },
    };
}
function isMatchingPreflightResolutionIssue(input) {
    const metadata = (0, preflight_resolution_marker_1.parsePreflightResolutionMetadata)(input.issue.body);
    return (metadata !== null &&
        metadata.resolutionKind === input.resolutionKind &&
        metadata.parentIssueId === input.parentIssueId &&
        metadata.resolutionKey === input.resolutionKey);
}
function buildPreflightResolutionWorkflowState(input) {
    return (0, state_1.buildPersistedWorkflowState)({
        workflowSurface: "issue",
        workflowTemplates: buildPreflightResolutionWorkflowTemplates({
            catalog: input.workflowTemplateCatalog,
            resolutionKind: input.resolutionKind,
        }),
        baseBranch: (0, issue_branch_target_1.resolveIssueCreationBaseBranch)({
            branchTarget: "effective_base_branch",
            config: input.issueContext.config,
            effectiveWorkflowState: input.parentWorkflowState,
        }),
        executionContract: (0, state_1.createDefaultWorkflowExecutionContract)(input.objective),
        plan: null,
        ...(input.parentWorkflowState?.configOverrides !== undefined
            ? { configOverrides: input.parentWorkflowState.configOverrides }
            : {}),
    });
}
function buildPreflightResolutionWorkflowTemplates(input) {
    const templatePath = resolvePreflightResolutionSystemWorkflowTemplatePath(input.resolutionKind);
    const workflowTemplates = (0, template_bindings_1.resolveWorkflowTemplateBindings)({
        catalog: input.catalog,
        selectors: { issue: { mode: "template", templatePath } },
    });
    if (workflowTemplates.issue.resolution.kind !== "template") {
        throw new Error(`Preflight resolution system workflow template not found: ${templatePath}`);
    }
    return workflowTemplates;
}
function resolvePreflightResolutionSystemWorkflowTemplatePath(resolutionKind) {
    switch (resolutionKind) {
        case "required-skills":
            return resolution_issue_2.SKILL_RESOLUTION_SYSTEM_WORKFLOW_TEMPLATE;
        case "required-mcp":
            return resolution_issue_1.MCP_RESOLUTION_SYSTEM_WORKFLOW_TEMPLATE;
        case "missing-workflow-template":
        case "workflow-template-fit":
            return WORKFLOW_MAINTENANCE_TEMPLATE_PATH;
    }
}
function buildPreflightResolutionTrackerFields(issueContext, parentIssue) {
    const fields = {
        assignees: parentIssue.assignees,
        labelNames: [issueContext.config.ticketTracker.workflowLabels.aiReady],
    };
    if (parentIssue.milestoneRef !== undefined) {
        fields.milestoneRef = parentIssue.milestoneRef;
    }
    if (parentIssue.projectRef !== undefined) {
        fields.projectRef = parentIssue.projectRef;
    }
    return fields;
}
