"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.writeReleaseNotesDraft = writeReleaseNotesDraft;
exports.renderReleaseNotesMarkdown = renderReleaseNotesMarkdown;
exports.renderHighLevelReleaseSummary = renderHighLevelReleaseSummary;
exports.appendCompletedWorkSection = appendCompletedWorkSection;
exports.appendUserVisibleBehaviorSection = appendUserVisibleBehaviorSection;
exports.appendKnownFollowUpWorkSection = appendKnownFollowUpWorkSection;
exports.appendSourceTraceSection = appendSourceTraceSection;
exports.createMilestoneTracePath = createMilestoneTracePath;
exports.humanizePlanningGroupLabel = humanizePlanningGroupLabel;
exports.humanizeSlug = humanizeSlug;
exports.formatHumanList = formatHumanList;
exports.shortenReleaseNoteLine = shortenReleaseNoteLine;
exports.normalizeFollowUpLine = normalizeFollowUpLine;
exports.uniqueStrings = uniqueStrings;
// Responsibility-focused extraction from release-notes.ts.
const node_fs_1 = __importDefault(require("node:fs"));
const node_path_1 = __importDefault(require("node:path"));
const cli_constants_1 = require("../../../lib/config/cli-constants");
const release_notes_contracts_1 = require("./release-notes-contracts");
const release_notes_evidence_1 = require("./release-notes-evidence");
function writeReleaseNotesDraft(options) {
    const bundleDirectory = node_path_1.default.join(options.versionDirectory, release_notes_contracts_1.RELEASE_DOWNLOAD_BUNDLE_DIRECTORY);
    const releaseNotesPath = node_path_1.default.join(bundleDirectory, cli_constants_1.RELEASE_NOTES_FILENAME);
    const releaseNotesPathRelative = `${options.versionDirectoryRelative}/${release_notes_contracts_1.RELEASE_DOWNLOAD_BUNDLE_DIRECTORY}/${cli_constants_1.RELEASE_NOTES_FILENAME}`;
    const sourceSummary = {
        ...options.sourceSummary,
        status: 'generated',
    };
    node_fs_1.default.mkdirSync(bundleDirectory, { recursive: true });
    node_fs_1.default.writeFileSync(releaseNotesPath, renderReleaseNotesMarkdown({
        repositoryRoot: options.repositoryRoot,
        version: options.version,
        generatedPath: releaseNotesPathRelative,
        sourceSummary,
    }));
    return {
        status: 'created',
        path: releaseNotesPathRelative,
        sourceSummary,
    };
}
function renderReleaseNotesMarkdown(options) {
    const sources = options.sourceSummary.selectedSources
        .map((source) => (0, release_notes_evidence_1.readRenderedSource)(options.repositoryRoot, source))
        .sort(release_notes_evidence_1.compareRenderedSources);
    const lines = [
        `# Day Shift ${options.version} Release Notes`,
        '',
        renderHighLevelReleaseSummary(sources),
        '',
        '## Completed Work',
        '',
    ];
    appendCompletedWorkSection(lines, sources);
    appendUserVisibleBehaviorSection(lines, sources);
    appendKnownFollowUpWorkSection(lines, sources);
    appendSourceTraceSection(lines, sources);
    return lines.join('\n');
}
function renderHighLevelReleaseSummary(sources) {
    const milestoneLabels = uniqueStrings(sources
        .map((source) => (0, release_notes_evidence_1.createPlanningGroupLabel)(source.metadata))
        .filter((label) => label !== 'Planning Evidence')
        .map((label) => humanizePlanningGroupLabel(label)));
    if (milestoneLabels.length === 0) {
        return 'This release contains the completed planning work selected for this version.';
    }
    if (milestoneLabels.length === 1) {
        return `This release completes ${milestoneLabels[0]}.`;
    }
    return `This release completes ${formatHumanList(milestoneLabels)}.`;
}
function appendCompletedWorkSection(lines, sources) {
    const reconciliationSources = sources.filter((source) => source.kind === 'milestone-reconciliation');
    if (reconciliationSources.length === 0) {
        lines.push('- No completed milestone reconciliation evidence was selected for this release.', '');
        return;
    }
    for (const source of reconciliationSources) {
        const label = source.title ?? humanizePlanningGroupLabel((0, release_notes_evidence_1.createPlanningGroupLabel)(source.metadata));
        lines.push(`- ${label}`);
        if (source.summary.length === 0) {
            lines.push('  - Completed milestone reconciliation evidence was selected for this release.');
        }
        else {
            for (const item of source.summary) {
                lines.push(`  - ${item}`);
            }
        }
    }
    lines.push('');
}
function appendUserVisibleBehaviorSection(lines, sources) {
    const items = uniqueStrings(sources
        .filter((source) => source.kind === 'implementation-summary')
        .flatMap((source) => (source.summary.length > 0 ? source.summary : source.behavior))
        .map(shortenReleaseNoteLine)
        .filter((item) => item.length > 0));
    lines.push('## User-Visible Behavior');
    lines.push('');
    if (items.length === 0) {
        lines.push('- No user-visible implementation summary was selected for this release.');
    }
    else {
        for (const item of items) {
            lines.push(`- ${item}`);
        }
    }
    lines.push('');
}
function appendKnownFollowUpWorkSection(lines, sources) {
    const followUps = uniqueStrings(sources
        .flatMap((source) => source.followUps)
        .map(normalizeFollowUpLine)
        .filter((item) => item.length > 0));
    lines.push('## Known Follow-Up Work');
    lines.push('');
    if (followUps.length === 0) {
        lines.push('- None.');
    }
    else {
        for (const followUp of followUps) {
            lines.push(`- ${followUp}`);
        }
    }
    lines.push('');
}
function appendSourceTraceSection(lines, sources) {
    const milestonePaths = uniqueStrings(sources.map((source) => createMilestoneTracePath(source.path)));
    lines.push('## Source Trace');
    lines.push('');
    if (milestonePaths.length === 0) {
        lines.push('- No selected milestone source trace.');
    }
    else {
        for (const milestonePath of milestonePaths) {
            lines.push(`- ${milestonePath}`);
        }
    }
    lines.push('');
}
function createMilestoneTracePath(sourcePath) {
    const normalizedPath = (0, release_notes_evidence_1.normalizeRelativePath)(sourcePath);
    const milestoneMatch = /^(.*\/milestones\/[^/]+)/.exec(normalizedPath);
    if (milestoneMatch !== null) {
        return milestoneMatch[1];
    }
    const taskMatch = /^(.*)\/tasks\/[^/]+\/implementation-summary\.md$/.exec(normalizedPath);
    if (taskMatch !== null) {
        return taskMatch[1];
    }
    return normalizedPath.replace(/\/reconciliation\.md$/, '').replace(/\/implementation-summary\.md$/, '');
}
function humanizePlanningGroupLabel(label) {
    return label
        .split('/')
        .map((part) => part.trim())
        .filter((part) => part.length > 0)
        .map(humanizeSlug)
        .join(' / ');
}
function humanizeSlug(value) {
    return value.replace(/^\d+-/, '').replace(/-/g, ' ').replace(/\s+/g, ' ').trim();
}
function formatHumanList(values) {
    if (values.length <= 2) {
        return values.join(' and ');
    }
    return `${values.slice(0, -1).join(', ')}, and ${values[values.length - 1]}`;
}
function shortenReleaseNoteLine(value) {
    const normalized = value
        .replace(/^(?:Completed|Passed|Met):\s*/i, '')
        .replace(/\s+/g, ' ')
        .trim();
    const sentenceMatch = /^(.+?[.!?])(?:\s|$)/.exec(normalized);
    const sentence = sentenceMatch?.[1] ?? normalized;
    const maxLength = 220;
    if (sentence.length <= maxLength) {
        return sentence;
    }
    const truncated = sentence.slice(0, maxLength - 1);
    const lastSpace = truncated.lastIndexOf(' ');
    return `${truncated.slice(0, lastSpace > 120 ? lastSpace : maxLength - 1).trimEnd()}.`;
}
function normalizeFollowUpLine(value) {
    const normalized = shortenReleaseNoteLine(value)
        .replace(/^(?:Candidate follow-up|Follow-up candidate|Follow-up(?: in task \d+)?|Discovered work|Residual risk):\s*/i, '')
        .trim();
    if (/^(?:none\b.*|not applicable|no additional .*|no new .*|no task-local .*|no .* follow-up.*)$/i.test(normalized)) {
        return '';
    }
    return normalized.length === 0 ? '' : `${normalized[0].toUpperCase()}${normalized.slice(1)}`;
}
function uniqueStrings(values) {
    return Array.from(new Set(values)).sort();
}
