"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.resolveStartedControllerChildConflict = resolveStartedControllerChildConflict;
exports.resolveOpenControllerChildIssues = resolveOpenControllerChildIssues;
exports.resolveCompletedControllerChildIssueByRef = resolveCompletedControllerChildIssueByRef;
const plan_progress_1 = require("../../../workflows/plan-progress");
const shared_1 = require("./shared");
const utils_1 = require("../spawn-child/utils");
async function resolveStartedControllerChildConflict(input) {
    const childStepsByKey = new Map(input.childIssueSteps.map((childIssueStep) => [
        childIssueStep.childKey,
        childIssueStep,
    ]));
    const existingChildLookup = await (0, shared_1.loadControllerChildIssueLookup)({
        ticketTracker: input.ticketTracker,
        issues: input.existingOpenChildren,
    });
    const existingChildrenById = new Map([...existingChildLookup.issueByChildKey.values()].map((childIssue) => [childIssue.id, childIssue]));
    for (const issue of input.existingOpenChildren) {
        const workflowState = existingChildLookup.workflowStateByIssueId.get(issue.id) ?? null;
        if (!(0, shared_1.isStartedControllerChildIssue)(issue, workflowState)) {
            continue;
        }
        const { childKey } = (0, shared_1.resolveControllerChildIdentity)(workflowState);
        if (childKey === null) {
            continue;
        }
        if (input.skipChildKeys?.has(childKey) === true) {
            continue;
        }
        if (workflowState === null) {
            continue;
        }
        const childIssueStep = childStepsByKey.get(childKey);
        if (childIssueStep === undefined) {
            return issue;
        }
        if ((0, shared_1.hasControllerChildParentStepContractSnapshotDrift)({
            childIssueStep,
            childWorkflowState: workflowState,
        })) {
            return issue;
        }
        const desiredSpec = (0, shared_1.buildControllerChildDesiredSpecForStep)({
            responseLanguage: input.responseLanguage,
            parentIssue: input.parentIssue,
            childIssueStep,
            childIssueSteps: input.allChildIssueSteps,
            allChildIssueSteps: input.allChildIssueSteps,
            catalog: input.catalog,
            parentWorkflowState: input.parentWorkflowState,
            followup: (0, shared_1.resolveStoredControllerChildFollowupState)(workflowState.followup),
            baseBranch: input.baseBranch,
            workflowLabels: input.workflowLabels,
            assignee: input.assignee,
        });
        const currentDependencies = await input.ticketTracker.listBlockingDependencies(issue.id);
        const currentDependencyKeys = currentDependencies
            .filter((dependency) => existingChildrenById.has(dependency.id))
            .map((dependency) => (0, shared_1.resolveControllerChildIdentity)(existingChildLookup.workflowStateByIssueId.get(dependency.id) ??
            null).childKey)
            .filter((dependencyKey) => dependencyKey !== null);
        const unresolvedChildKeys = new Set(input.childIssueSteps.map((candidateStep) => candidateStep.childKey));
        if (hasStartedControllerChildDrift({
            ...desiredSpec,
            dependsOn: desiredSpec.dependsOn.filter((dependencyKey) => unresolvedChildKeys.has(dependencyKey)),
        }, issue, workflowState, currentDependencyKeys, input.workflowLabels)) {
            return issue;
        }
    }
    return null;
}
async function resolveOpenControllerChildIssues(input) {
    const desiredChildKeys = new Set(input.childIssueSteps.map((childIssueStep) => childIssueStep.childKey));
    const liveBlockerIds = new Set(input.liveBlockers
        .filter((blocker) => blocker.isOpen)
        .map((blocker) => blocker.id));
    const canonicalStateByIssueId = await (0, shared_1.loadControllerChildCanonicalStateMap)({
        ticketTracker: input.ticketTracker,
        issues: input.openIssues,
    });
    const matches = new Map();
    for (const issue of [...input.openIssues].sort(utils_1.compareIssuesDeterministically)) {
        if (issue.id === input.parentIssue.id || !liveBlockerIds.has(issue.id)) {
            continue;
        }
        const workflowState = canonicalStateByIssueId.get(issue.id) ?? null;
        const childKey = resolveDesiredControllerChildMatchKey({
            issue,
            desiredChildKeys,
            workflowState,
        });
        if (childKey === null) {
            continue;
        }
        if (!(0, shared_1.isControllerChildForParent)({
            workflowState,
            parentDisplayId: input.parentIssue.displayId,
        })) {
            continue;
        }
        matches.set(childKey, issue);
    }
    for (const issue of [...input.openIssues].sort(utils_1.compareIssuesDeterministically)) {
        if (issue.id === input.parentIssue.id || liveBlockerIds.has(issue.id)) {
            continue;
        }
        const workflowState = canonicalStateByIssueId.get(issue.id) ?? null;
        const childKey = resolveDesiredControllerChildMatchKey({
            issue,
            desiredChildKeys,
            workflowState,
        });
        if (childKey === null || matches.has(childKey)) {
            continue;
        }
        if (!(0, shared_1.isControllerChildForParent)({
            workflowState,
            parentDisplayId: input.parentIssue.displayId,
        })) {
            continue;
        }
        matches.set(childKey, issue);
    }
    return [...matches.values()].sort(utils_1.compareIssuesDeterministically);
}
async function resolveCompletedControllerChildIssueByRef(input) {
    const childIssueRef = (0, shared_1.normalizeControllerChildIssueRef)(input.childIssueStep.childIssueRef);
    if (childIssueRef === null) {
        return null;
    }
    const issue = await input.ticketTracker.getIssueReference(childIssueRef);
    if (issue.isOpen) {
        return null;
    }
    const workflowState = await (0, shared_1.resolveControllerChildCanonicalWorkflowState)({
        ticketTracker: input.ticketTracker,
        issueId: issue.id,
    });
    if (workflowState === null) {
        return null;
    }
    if (!(0, shared_1.isControllerChildForParent)({
        workflowState,
        parentDisplayId: input.parentIssue.displayId,
        childKey: input.childIssueStep.childKey,
    })) {
        return null;
    }
    if (!(0, plan_progress_1.isClosedCompletedControllerChildIssue)({
        issue,
        workflowState,
    })) {
        return null;
    }
    return { issue, workflowState };
}
function hasStartedControllerChildDrift(desiredSpec, existingIssue, existingWorkflowState, currentDependencyKeys, workflowLabels) {
    return ((0, shared_1.buildDesiredControllerChildDriftFingerprint)(desiredSpec, workflowLabels) !==
        (0, shared_1.buildExistingControllerChildDriftFingerprint)({
            existingIssue,
            existingWorkflowState,
            currentDependencyKeys,
            workflowLabels,
        }));
}
function resolveDesiredControllerChildMatchKey(input) {
    const { childKey } = (0, shared_1.resolveControllerChildIdentity)(input.workflowState);
    if (childKey === null) {
        return null;
    }
    if (input.desiredChildKeys.has(childKey) ||
        (0, shared_1.isStartedControllerChildIssue)(input.issue, input.workflowState)) {
        return childKey;
    }
    return null;
}
