"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.formatWorkflowUpdate = formatWorkflowUpdate;
exports.parseWorkflowUpdate = parseWorkflowUpdate;
exports.isWorkflowUpdateComment = isWorkflowUpdateComment;
exports.findCurrentConsecutiveAiRuns = findCurrentConsecutiveAiRuns;
exports.findLatestNeedsHumanReason = findLatestNeedsHumanReason;
const catalog_1 = require("../i18n/catalog");
const display_duration_1 = require("../i18n/display-duration");
const comment_command_1 = require("../workflows/comment-command");
const publisher_events_1 = require("../workflows/publisher-events");
const canonical_workflow_state_1 = require("./canonical-workflow-state");
const WORKFLOW_UPDATE_DETAILS_SUMMARY_KEY = "workflowUpdate.detailsSummary";
const WORKFLOW_UPDATE_ACTION_HEADING_HUMAN_KEY = "workflowUpdate.actionHeading.human";
const WORKFLOW_UPDATE_ACTION_HEADING_AI_KEY = "workflowUpdate.actionHeading.ai";
const WORKFLOW_UPDATE_ACTION_HEADING_NEXT_KEY = "workflowUpdate.actionHeading.next";
function formatWorkflowUpdate(comment, options = {}) {
    const language = options.language ?? catalog_1.DEFAULT_APP_LOCALE;
    const summary = normalizeDisplaySectionValue(comment.summary);
    const next = normalizeDisplaySectionValue(comment.next);
    if (summary === null || next === null) {
        throw new Error((0, catalog_1.translate)(language, "workflowUpdate.error.summaryAndNextRequired"));
    }
    const blocks = [renderWorkflowUpdateHeading(comment, language), ""];
    blocks.push(summary);
    const visibleWorkflowStateLink = renderVisibleWorkflowStateLink(comment, language);
    if (visibleWorkflowStateLink !== null) {
        blocks.push("", visibleWorkflowStateLink);
    }
    blocks.push("", renderWorkflowUpdateActionHeading(comment, language), "", next, "", "<details>", `<summary>${(0, catalog_1.translate)(language, WORKFLOW_UPDATE_DETAILS_SUMMARY_KEY)}</summary>`, "", ...buildWorkflowUpdateMetadataLines(comment, language), "", "</details>", "");
    return blocks.join("\n");
}
function parseWorkflowUpdate(markdown) {
    if (!isWorkflowUpdateComment(markdown)) {
        return null;
    }
    const metadata = parseMetadataSection(extractDetailsBlock(markdown));
    const next = extractActionSection(markdown);
    const rawSummary = extractSummaryWithoutHeading(markdown, metadata?.canonicalWorkflowStateUrl);
    const summary = rawSummary === undefined
        ? undefined
        : normalizeSectionValue(stripVisibleWorkflowStateLink(rawSummary, metadata?.canonicalWorkflowStateUrl ?? null));
    if (metadata === null || !summary || !next) {
        return null;
    }
    const parsed = {
        event: metadata.event,
        consecutiveAiRuns: metadata.consecutiveAiRuns,
        summary,
        next,
    };
    if (metadata.dedupeKey !== null) {
        parsed.dedupeKey = metadata.dedupeKey;
    }
    if (metadata.totalAiRunDuration !== null) {
        parsed.totalAiRunDuration = metadata.totalAiRunDuration;
    }
    if (metadata.workerOutcome !== null) {
        parsed.workerOutcome = metadata.workerOutcome;
    }
    if (metadata.terminalSuccess) {
        parsed.terminalSuccess = true;
    }
    if (metadata.needsHumanReason !== null) {
        parsed.needsHumanReason = metadata.needsHumanReason;
    }
    if (metadata.workflowTemplateLabel !== null) {
        parsed.workflowTemplateLabel = metadata.workflowTemplateLabel;
    }
    if (metadata.canonicalWorkflowStateUrl !== null) {
        parsed.canonicalWorkflowStateUrl = metadata.canonicalWorkflowStateUrl;
    }
    return parsed;
}
function isWorkflowUpdateComment(markdown) {
    const trimmed = markdown.trimStart();
    const firstLine = trimmed.split("\n", 1)[0]?.trim() ?? "";
    return (isDynamicWorkflowUpdateHeading(firstLine) &&
        hasWorkflowUpdateMetadataEventLine(markdown));
}
function findCurrentConsecutiveAiRuns(comments) {
    let candidate = null;
    for (const comment of [...comments].reverse()) {
        if ((0, canonical_workflow_state_1.isCanonicalWorkflowStateComment)(comment.body)) {
            continue;
        }
        if ((0, comment_command_1.isOperationalCommandComment)(comment.body)) {
            continue;
        }
        if (!isWorkflowUpdateComment(comment.body)) {
            return candidate ?? 0;
        }
        if (candidate === null) {
            const parsed = parseWorkflowUpdate(comment.body);
            if (parsed) {
                candidate = parsed.consecutiveAiRuns;
            }
        }
    }
    return candidate ?? 0;
}
function findLatestNeedsHumanReason(comments) {
    for (const comment of [...comments].reverse()) {
        const parsed = parseWorkflowUpdate(comment.body);
        if (parsed === null) {
            continue;
        }
        return parsed.needsHumanReason ?? null;
    }
    return null;
}
function parseMetadataSection(rawMetadata) {
    if (!rawMetadata) {
        return null;
    }
    const metadata = new Map();
    for (const line of rawMetadata.split("\n")) {
        const trimmed = line.trim();
        if (trimmed.length === 0) {
            continue;
        }
        if (/^<details\b/i.test(trimmed) ||
            /^<\/details>/i.test(trimmed) ||
            /^<summary\b/i.test(trimmed) ||
            /^<\/summary>/i.test(trimmed)) {
            continue;
        }
        const metadataLine = trimmed.match(/^[-*+]\s+(.+)$/)?.[1];
        if (metadataLine === undefined) {
            return null;
        }
        const separatorIndex = metadataLine.indexOf(":");
        if (separatorIndex === -1) {
            return null;
        }
        const key = metadataLine.slice(0, separatorIndex).trim();
        const value = metadataLine.slice(separatorIndex + 1).trim();
        if (key.length === 0 || value.length === 0) {
            return null;
        }
        metadata.set(key, value);
    }
    const event = getLocalizedMetadataValue(metadata, "workflowUpdate.metadata.event");
    const workerOutcome = getLocalizedMetadataValue(metadata, "workflowUpdate.metadata.workerOutcome");
    const dedupeKey = getLocalizedMetadataValue(metadata, "workflowUpdate.metadata.dedupeKey");
    const consecutiveAiRunsValue = getLocalizedMetadataValue(metadata, "workflowUpdate.metadata.consecutiveAiRuns");
    const totalAiRunDuration = normalizeSectionValue(getLocalizedMetadataValue(metadata, "workflowUpdate.metadata.totalAiRunHours"));
    const normalizedEvent = (0, publisher_events_1.normalizeWorkflowVisibleEventValue)(event);
    const normalizedWorkerOutcome = (0, publisher_events_1.normalizeWorkerOutcomeValue)(workerOutcome);
    if (normalizedEvent === null || consecutiveAiRunsValue === undefined) {
        return null;
    }
    const consecutiveAiRuns = Number(consecutiveAiRunsValue);
    if (!Number.isInteger(consecutiveAiRuns) || consecutiveAiRuns < 0) {
        return null;
    }
    const needsHumanReason = normalizeSectionValue(getLocalizedMetadataValue(metadata, "workflowUpdate.metadata.needsHumanReason"));
    const normalizedNeedsHumanReason = needsHumanReason === null
        ? null
        : (0, publisher_events_1.normalizeWorkflowNeedsHumanReasonValue)(needsHumanReason);
    if (needsHumanReason !== null && normalizedNeedsHumanReason === null) {
        return null;
    }
    return {
        event: normalizedEvent,
        dedupeKey: normalizeSectionValue(dedupeKey),
        workerOutcome: normalizedWorkerOutcome?.workerOutcome ?? null,
        terminalSuccess: normalizedWorkerOutcome?.terminalSuccess ?? false,
        consecutiveAiRuns,
        totalAiRunDuration,
        needsHumanReason: normalizedNeedsHumanReason,
        workflowTemplateLabel: normalizeSectionValue(getLocalizedMetadataValue(metadata, "workflowUpdate.metadata.workflowTemplate")),
        canonicalWorkflowStateUrl: normalizeCanonicalWorkflowStateUrl(getLocalizedMetadataValue(metadata, "workflowUpdate.metadata.workflowStateComment")),
    };
}
function normalizeSectionValue(value) {
    if (value === undefined || value === null) {
        return null;
    }
    const text = value.trim();
    return text.length > 0 ? text : null;
}
function normalizeDisplaySectionValue(value) {
    if (value === undefined || value === null) {
        return null;
    }
    const normalizedNewlines = value
        .replaceAll("\\r\\n", "\n")
        .replaceAll("\\n", "\n")
        .replaceAll("\\r", "\n");
    return normalizeSectionValue(normalizedNewlines);
}
function normalizeCanonicalWorkflowStateUrl(value) {
    const normalized = normalizeSectionValue(value);
    if (normalized === null) {
        return null;
    }
    return parseStandaloneMarkdownLinkUrl(normalized) ?? normalized;
}
function buildWorkflowUpdateMetadataLines(comment, language) {
    const lines = [
        `- ${(0, catalog_1.translate)(language, "workflowUpdate.metadata.event")}: ${(0, publisher_events_1.renderWorkflowVisibleEventValue)(comment.event, language)}`,
        `- ${(0, catalog_1.translate)(language, "workflowUpdate.metadata.consecutiveAiRuns")}: ${comment.consecutiveAiRuns}`,
    ];
    const dedupeKey = normalizeSectionValue(comment.dedupeKey);
    if (dedupeKey !== null) {
        lines.push(`- ${(0, catalog_1.translate)(language, "workflowUpdate.metadata.dedupeKey")}: ${dedupeKey}`);
    }
    if (comment.totalAiRunHours !== undefined) {
        lines.push(`- ${(0, catalog_1.translate)(language, "workflowUpdate.metadata.totalAiRunHours")}: ${(0, display_duration_1.formatHumanAiRunHours)(comment.totalAiRunHours, language)}`);
    }
    if (comment.workerOutcome !== undefined) {
        lines.push(`- ${(0, catalog_1.translate)(language, "workflowUpdate.metadata.workerOutcome")}: ${(0, publisher_events_1.renderWorkerOutcomeValue)(comment.workerOutcome, language, comment.terminalSuccess === true ||
            comment.event === publisher_events_1.WORKFLOW_VISIBLE_EVENTS.workflowCompleted)}`);
    }
    if (comment.needsHumanReason !== undefined) {
        lines.push(`- ${(0, catalog_1.translate)(language, "workflowUpdate.metadata.needsHumanReason")}: ${(0, publisher_events_1.renderWorkflowNeedsHumanReasonValue)(comment.needsHumanReason, language)}`);
    }
    const workflowTemplateLabel = normalizeSectionValue(comment.workflowTemplateLabel);
    if (workflowTemplateLabel !== null) {
        lines.push(`- ${(0, catalog_1.translate)(language, "workflowUpdate.metadata.workflowTemplate")}: ${workflowTemplateLabel}`);
    }
    const canonicalWorkflowStateUrl = normalizeSectionValue(comment.canonicalWorkflowStateUrl);
    if (canonicalWorkflowStateUrl !== null) {
        lines.push(`- ${(0, catalog_1.translate)(language, "workflowUpdate.metadata.workflowStateComment")}: [${(0, catalog_1.translate)(language, "workflowUpdate.workflowStateLink.currentStatus")}](${canonicalWorkflowStateUrl})`);
    }
    return lines;
}
function renderWorkflowUpdateHeading(comment, language) {
    const explicitTitle = normalizeSectionValue(comment.title);
    const title = resolveWorkflowUpdateHeadingTitle(comment, language, explicitTitle);
    return `## ${title}`;
}
function resolveWorkflowUpdateHeadingTitle(comment, language, explicitTitle) {
    if (explicitTitle === null) {
        return renderDefaultWorkflowUpdateTitle(comment, language);
    }
    if (isWorkflowUpdateHeadingTitle(explicitTitle)) {
        return explicitTitle;
    }
    const status = resolveWorkflowUpdateStatus(comment);
    return `${(0, catalog_1.translate)(language, `workflowUpdate.status.${status}`)}: ${explicitTitle}`;
}
function renderDefaultWorkflowUpdateTitle(comment, language) {
    const status = resolveWorkflowUpdateStatus(comment);
    return `${(0, catalog_1.translate)(language, `workflowUpdate.status.${status}`)}: ${(0, catalog_1.translate)(language, resolveWorkflowUpdateTitleKey(comment, status))}`;
}
function resolveWorkflowUpdateStatus(comment) {
    if (comment.workerOutcome === "fail" ||
        comment.event === publisher_events_1.WORKFLOW_VISIBLE_EVENTS.workflowFailed) {
        return "failed";
    }
    if (comment.terminalSuccess === true ||
        comment.event === publisher_events_1.WORKFLOW_VISIBLE_EVENTS.workflowCompleted) {
        return "complete";
    }
    if (comment.workerOutcome === "wait_human" ||
        comment.needsHumanReason !== undefined ||
        comment.event === publisher_events_1.WORKFLOW_VISIBLE_EVENTS.humanAttentionRequested ||
        comment.event === publisher_events_1.WORKFLOW_VISIBLE_EVENTS.issueReviewReady ||
        comment.event === publisher_events_1.WORKFLOW_VISIBLE_EVENTS.prReviewReady) {
        return "waiting";
    }
    return "inProgress";
}
function resolveWorkflowUpdateTitleKey(comment, status) {
    if (status === "failed") {
        return "workflowUpdate.title.failed.default";
    }
    if (status === "complete") {
        return "workflowUpdate.title.complete.default";
    }
    if (status === "waiting") {
        if (comment.needsHumanReason === publisher_events_1.WORKFLOW_NEEDS_HUMAN_REASONS.startApproval) {
            return "workflowUpdate.title.waiting.startApproval";
        }
        if (comment.needsHumanReason === publisher_events_1.WORKFLOW_NEEDS_HUMAN_REASONS.reviewReady ||
            comment.event === publisher_events_1.WORKFLOW_VISIBLE_EVENTS.issueReviewReady ||
            comment.event === publisher_events_1.WORKFLOW_VISIBLE_EVENTS.prReviewReady) {
            return "workflowUpdate.title.waiting.review";
        }
        return "workflowUpdate.title.waiting.default";
    }
    if (comment.event === publisher_events_1.WORKFLOW_VISIBLE_EVENTS.workflowStarted) {
        return "workflowUpdate.title.inProgress.started";
    }
    if (comment.event === publisher_events_1.WORKFLOW_VISIBLE_EVENTS.replanQueued) {
        return "workflowUpdate.title.inProgress.replan";
    }
    return "workflowUpdate.title.inProgress.default";
}
function renderWorkflowUpdateActionHeading(comment, language) {
    const status = resolveWorkflowUpdateStatus(comment);
    if (status === "waiting") {
        return `**${(0, catalog_1.translate)(language, WORKFLOW_UPDATE_ACTION_HEADING_HUMAN_KEY)}**`;
    }
    if (status === "inProgress") {
        return `**${(0, catalog_1.translate)(language, WORKFLOW_UPDATE_ACTION_HEADING_AI_KEY)}**`;
    }
    return `**${(0, catalog_1.translate)(language, WORKFLOW_UPDATE_ACTION_HEADING_NEXT_KEY)}**`;
}
function renderVisibleWorkflowStateLink(comment, language) {
    const canonicalWorkflowStateUrl = normalizeSectionValue(comment.canonicalWorkflowStateUrl);
    if (canonicalWorkflowStateUrl === null) {
        return null;
    }
    const label = comment.needsHumanReason === publisher_events_1.WORKFLOW_NEEDS_HUMAN_REASONS.startApproval
        ? (0, catalog_1.translate)(language, "workflowUpdate.workflowStateLink.startApproval")
        : (0, catalog_1.translate)(language, "workflowUpdate.workflowStateLink.currentStatus");
    return `[${label}](${canonicalWorkflowStateUrl})`;
}
function extractSummaryWithoutHeading(markdown, canonicalWorkflowStateUrl) {
    const lines = markdown.split("\n");
    const headingIndex = lines.findIndex((line) => isDynamicWorkflowUpdateHeading(line.trim()));
    if (headingIndex === -1) {
        return undefined;
    }
    const summaryLines = [];
    let sawBodyLine = false;
    for (const rawLine of lines.slice(headingIndex + 1)) {
        const trimmed = rawLine.trim();
        if (!sawBodyLine && trimmed.length === 0) {
            continue;
        }
        if (isWorkflowUpdateActionHeading(trimmed) ||
            /^<details\b/i.test(trimmed)) {
            break;
        }
        sawBodyLine = true;
        summaryLines.push(rawLine);
    }
    const strippedSummary = stripVisibleWorkflowStateLink(summaryLines.join("\n"), normalizeSectionValue(canonicalWorkflowStateUrl));
    return normalizeSectionValue(strippedSummary) ?? undefined;
}
function extractActionSection(markdown) {
    const lines = markdown.split("\n");
    const headingIndex = lines.findIndex((line) => isWorkflowUpdateActionHeading(line.trim()));
    if (headingIndex === -1) {
        return undefined;
    }
    const nextLines = [];
    let sawBodyLine = false;
    for (const rawLine of lines.slice(headingIndex + 1)) {
        const trimmed = rawLine.trim();
        if (!sawBodyLine && trimmed.length === 0) {
            continue;
        }
        if (/^<details\b/i.test(trimmed)) {
            break;
        }
        sawBodyLine = true;
        nextLines.push(rawLine);
    }
    return normalizeSectionValue(nextLines.join("\n")) ?? undefined;
}
function extractDetailsBlock(markdown) {
    const match = markdown.match(/<details\b[^>]*>([\s\S]*?)<\/details>/i);
    return match?.[1]?.trim();
}
function hasWorkflowUpdateMetadataEventLine(markdown) {
    return (0, catalog_1.translateAllLocales)("workflowUpdate.metadata.event").some((label) => {
        const pattern = new RegExp(`(?:^|\\n)\\s*[-*+]\\s+${escapeRegExp(label)}\\s*:`);
        return pattern.test(markdown);
    });
}
function isDynamicWorkflowUpdateHeading(line) {
    const title = line.match(/^##\s+(.+)$/)?.[1]?.trim();
    if (title === undefined) {
        return false;
    }
    return isWorkflowUpdateHeadingTitle(title);
}
function isWorkflowUpdateHeadingTitle(title) {
    return (0, catalog_1.translateAllLocales)("workflowUpdate.status.waiting")
        .concat((0, catalog_1.translateAllLocales)("workflowUpdate.status.inProgress"), (0, catalog_1.translateAllLocales)("workflowUpdate.status.complete"), (0, catalog_1.translateAllLocales)("workflowUpdate.status.failed"))
        .some((label) => title.startsWith(`${label}:`) || title.startsWith(`${label}：`));
}
function isWorkflowUpdateActionHeading(line) {
    return getLocalizedWorkflowUpdateActionHeadings().includes(line.trim());
}
function getLocalizedWorkflowUpdateActionHeadings() {
    return [
        WORKFLOW_UPDATE_ACTION_HEADING_HUMAN_KEY,
        WORKFLOW_UPDATE_ACTION_HEADING_AI_KEY,
        WORKFLOW_UPDATE_ACTION_HEADING_NEXT_KEY,
    ].flatMap((key) => (0, catalog_1.translateAllLocales)(key).map((heading) => `**${heading}**`));
}
function stripVisibleWorkflowStateLink(markdown, canonicalWorkflowStateUrl) {
    if (canonicalWorkflowStateUrl === null) {
        return markdown.trim();
    }
    return markdown
        .split("\n")
        .filter((line) => {
        const linkUrl = parseStandaloneMarkdownLinkUrl(line);
        return linkUrl === null || linkUrl !== canonicalWorkflowStateUrl;
    })
        .join("\n")
        .trim();
}
function parseStandaloneMarkdownLinkUrl(line) {
    const match = line.trim().match(/^\[[^\]]+\]\(([^)]+)\)$/);
    if (!match) {
        return null;
    }
    return match[1]?.trim().replace(/^<|>$/g, "") ?? null;
}
function escapeRegExp(value) {
    return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
function getLocalizedMetadataValue(metadata, labelKey) {
    for (const label of (0, catalog_1.translateAllLocales)(labelKey)) {
        const value = metadata.get(label);
        if (value !== undefined) {
            return value;
        }
    }
    return undefined;
}
