"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.resolveReleaseNotesPreviousMarker = resolveReleaseNotesPreviousMarker;
exports.selectReleaseNotesPlanningEvidence = selectReleaseNotesPlanningEvidence;
exports.createReleaseNotesSourceSummary = createReleaseNotesSourceSummary;
exports.collectPreviouslyReleasedPlanningArtifacts = collectPreviouslyReleasedPlanningArtifacts;
exports.collectPreviouslyReleasedPlanningSources = collectPreviouslyReleasedPlanningSources;
exports.mergeReleasedPlanningSources = mergeReleasedPlanningSources;
exports.readPreviousReleaseNotesSourceSummary = readPreviousReleaseNotesSourceSummary;
exports.createSkippedReleaseNotesDraft = createSkippedReleaseNotesDraft;
exports.createNotApplicableReleaseNotesDraft = createNotApplicableReleaseNotesDraft;
// 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 errors_1 = require("../../../lib/errors");
const release_notes_contracts_1 = require("./release-notes-contracts");
const release_notes_evidence_1 = require("./release-notes-evidence");
function resolveReleaseNotesPreviousMarker(options) {
    const currentVersion = (0, release_notes_evidence_1.requireStableVersion)(options.version, 'current release version');
    if (currentVersion.version === '0.1.0') {
        return {
            kind: 'first-public-release',
            marker: 'planning-history-start',
            version: null,
            sources: [
                {
                    source: 'first-public-release',
                    version: '0.1.0',
                    path: '.day-shift/planning',
                },
            ],
        };
    }
    const sources = [
        ...(0, release_notes_evidence_1.collectManifestMarkerEvidence)(options, currentVersion),
        ...(0, release_notes_evidence_1.collectLocalReleaseMetadataMarkerEvidence)(options, currentVersion),
        ...(0, release_notes_evidence_1.collectReleaseTagMarkerEvidence)(options, currentVersion),
    ];
    const versions = Array.from(new Set(sources.map((source) => source.version))).sort(release_notes_evidence_1.compareStableVersions);
    if (versions.length === 0) {
        throw (0, errors_1.createUsageError)('Release notes require a previous release marker for versions after 0.1.0.', [
            'Reason: missing-previous-release-marker',
            `Current version: ${currentVersion.version}`,
            `Release output root: ${options.releaseRootRelative}`,
            'Checked sources: release manifests, local release metadata, release tags',
            'Recovery: restore at least one previous release marker before generating release notes source metadata.',
            'Exit behavior: exits before generated release notes or manifest source metadata are emitted.',
        ]);
    }
    const selectedVersion = versions[versions.length - 1];
    return {
        kind: 'previous-release',
        marker: `release:${selectedVersion}`,
        version: selectedVersion,
        sources: sources.filter((source) => source.version === selectedVersion).sort(release_notes_evidence_1.compareMarkerEvidence),
    };
}
function selectReleaseNotesPlanningEvidence(options) {
    const planningRootRelative = (0, release_notes_evidence_1.normalizeRelativePath)(options.planningRoot ?? '.day-shift/planning');
    const planningRoot = node_path_1.default.resolve(options.repositoryRoot, planningRootRelative);
    const selectedSources = [];
    const excludedSources = [];
    const explicitIncludes = new Set((options.explicitlyIncludedPlanningArtifacts ?? []).map((artifactPath) => (0, release_notes_evidence_1.normalizeRelativePath)(artifactPath)));
    const previouslyReleased = new Set((options.previouslyReleasedPlanningArtifacts ?? []).map((artifactPath) => (0, release_notes_evidence_1.normalizeRelativePath)(artifactPath)));
    if (node_fs_1.default.existsSync(planningRoot) && node_fs_1.default.statSync(planningRoot).isDirectory()) {
        for (const filePath of (0, release_notes_evidence_1.collectMarkdownFiles)(planningRoot)) {
            const artifactPath = (0, release_notes_evidence_1.toRepositoryRelativePath)(options.repositoryRoot, filePath);
            const artifact = (0, release_notes_evidence_1.readPlanningArtifact)(filePath);
            const explicitlyIncluded = explicitIncludes.has(artifactPath);
            if ((0, release_notes_evidence_1.isPrivateLicenseOperationReleaseNoteSource)(artifactPath)) {
                explicitIncludes.delete(artifactPath);
                continue;
            }
            if (explicitlyIncluded) {
                selectedSources.push({
                    kind: 'explicit-release-metadata-include',
                    path: artifactPath,
                    title: artifact.title,
                });
                explicitIncludes.delete(artifactPath);
                continue;
            }
            if (previouslyReleased.has(artifactPath)) {
                excludedSources.push({ path: artifactPath, reason: 'already-included-in-previous-release' });
                continue;
            }
            if (artifactPath.endsWith('/implementation-summary.md')) {
                if (artifact.metadata.status === 'completed' && artifact.metadata.implementation_status === 'completed') {
                    selectedSources.push({
                        kind: 'implementation-summary',
                        path: artifactPath,
                        title: artifact.title,
                    });
                }
                else {
                    excludedSources.push({ path: artifactPath, reason: 'draft-or-pending' });
                }
                continue;
            }
            if (artifactPath.endsWith('/reconciliation.md')) {
                if (artifact.metadata.status === 'completed' && artifact.metadata.reconciliation_status === 'completed') {
                    selectedSources.push({
                        kind: 'milestone-reconciliation',
                        path: artifactPath,
                        title: artifact.title,
                    });
                }
                else {
                    excludedSources.push({ path: artifactPath, reason: 'draft-or-pending' });
                }
                continue;
            }
            if (artifactPath.endsWith('/task-definition.md') || artifactPath.endsWith('/overview.md')) {
                excludedSources.push({ path: artifactPath, reason: 'proposal-only' });
            }
            else {
                excludedSources.push({ path: artifactPath, reason: 'unsupported-planning-artifact' });
            }
        }
    }
    for (const missingPath of Array.from(explicitIncludes).sort()) {
        excludedSources.push({
            path: missingPath,
            reason: 'explicit-include-missing',
        });
    }
    const sortedSelectedSources = selectedSources.sort(release_notes_evidence_1.comparePlanningSources);
    const sortedExcludedSources = excludedSources.sort(release_notes_evidence_1.comparePlanningExclusions);
    return {
        planningRoot: planningRootRelative,
        selectedSources: sortedSelectedSources,
        excludedSources: sortedExcludedSources,
        counts: {
            selectedImplementationSummaries: sortedSelectedSources.filter((source) => source.kind === 'implementation-summary').length,
            selectedMilestoneReconciliations: sortedSelectedSources.filter((source) => source.kind === 'milestone-reconciliation').length,
            explicitIncludes: sortedSelectedSources.filter((source) => source.kind === 'explicit-release-metadata-include')
                .length,
            excludedDraftOrPending: sortedExcludedSources.filter((source) => source.reason === 'draft-or-pending').length,
            excludedProposalOnly: sortedExcludedSources.filter((source) => source.reason === 'proposal-only').length,
            excludedUnsupported: sortedExcludedSources.filter((source) => source.reason === 'unsupported-planning-artifact' || source.reason === 'explicit-include-missing').length,
        },
    };
}
function createReleaseNotesSourceSummary(options) {
    const marker = resolveReleaseNotesPreviousMarker(options);
    const previouslyReleasedSources = collectPreviouslyReleasedPlanningSources(options.repositoryRoot, marker);
    const previouslyReleasedPlanningArtifacts = previouslyReleasedSources.map((source) => source.path);
    const selection = selectReleaseNotesPlanningEvidence({
        repositoryRoot: options.repositoryRoot,
        planningRoot: options.planningRoot,
        explicitlyIncludedPlanningArtifacts: options.explicitlyIncludedPlanningArtifacts,
        previouslyReleasedPlanningArtifacts,
    });
    return {
        status: options.notesGenerated ? 'generated' : 'not-generated',
        previousReleaseMarker: marker.marker,
        planningArtifactRange: `${marker.marker}..${selection.planningRoot}`,
        marker,
        counts: {
            ...selection.counts,
            selectedSources: selection.selectedSources.length,
            excludedSources: selection.excludedSources.length,
        },
        selectedSources: selection.selectedSources,
        excludedSources: selection.excludedSources,
        releasedSources: mergeReleasedPlanningSources(previouslyReleasedSources, selection.selectedSources),
    };
}
function collectPreviouslyReleasedPlanningArtifacts(repositoryRoot, marker) {
    return collectPreviouslyReleasedPlanningSources(repositoryRoot, marker).map((source) => source.path);
}
function collectPreviouslyReleasedPlanningSources(repositoryRoot, marker) {
    if (marker.kind === 'first-public-release') {
        return [];
    }
    const sources = new Map();
    const visitedMarkerPaths = new Set();
    const collectMarkerPath = (markerPath) => {
        if (markerPath === null || markerPath.startsWith('tag:')) {
            return;
        }
        const normalizedMarkerPath = (0, release_notes_evidence_1.normalizeRelativePath)(markerPath);
        if (visitedMarkerPaths.has(normalizedMarkerPath)) {
            return;
        }
        visitedMarkerPaths.add(normalizedMarkerPath);
        const sourceSummary = readPreviousReleaseNotesSourceSummary(repositoryRoot, normalizedMarkerPath);
        for (const releasedSource of sourceSummary?.releasedSources ?? sourceSummary?.selectedSources ?? []) {
            if (typeof releasedSource.path === 'string' && releasedSource.path.length > 0) {
                const normalizedPath = (0, release_notes_evidence_1.normalizeRelativePath)(releasedSource.path);
                sources.set(normalizedPath, { ...releasedSource, path: normalizedPath });
            }
        }
        if (sourceSummary?.cumulative !== true) {
            for (const previousMarkerPath of sourceSummary?.previousMarkerPaths ?? []) {
                collectMarkerPath(previousMarkerPath);
            }
        }
    };
    for (const source of marker.sources) {
        collectMarkerPath(source.path);
    }
    return Array.from(sources.values()).sort(release_notes_evidence_1.comparePlanningSources);
}
function mergeReleasedPlanningSources(previous, current) {
    const sources = new Map();
    for (const source of [...previous, ...current]) {
        sources.set((0, release_notes_evidence_1.normalizeRelativePath)(source.path), {
            ...source,
            path: (0, release_notes_evidence_1.normalizeRelativePath)(source.path),
        });
    }
    return Array.from(sources.values()).sort(release_notes_evidence_1.comparePlanningSources);
}
function readPreviousReleaseNotesSourceSummary(repositoryRoot, markerPath) {
    if (markerPath === null || markerPath.startsWith('tag:')) {
        return null;
    }
    const resolvedPath = node_path_1.default.resolve(repositoryRoot, (0, release_notes_evidence_1.normalizeRelativePath)(markerPath));
    if (!node_fs_1.default.existsSync(resolvedPath) || !node_fs_1.default.statSync(resolvedPath).isFile()) {
        return null;
    }
    const record = (0, release_notes_evidence_1.readJsonRecord)(resolvedPath);
    const directSummary = record.releaseNotesSourceSummary;
    const manifestReleaseNotes = (0, release_notes_evidence_1.isRecord)(record.releaseNotes) ? record.releaseNotes : null;
    const manifestSummary = manifestReleaseNotes?.sourceSummary;
    const compactProvenance = (0, release_notes_evidence_1.isRecord)(manifestSummary) && (0, release_notes_evidence_1.isRecord)(manifestSummary.provenance)
        ? manifestSummary.provenance
        : null;
    const provenancePath = typeof compactProvenance?.path === 'string' ? compactProvenance.path : null;
    const provenanceRecord = provenancePath === null
        ? null
        : (0, release_notes_evidence_1.readJsonRecord)(node_path_1.default.resolve(repositoryRoot, (0, release_notes_evidence_1.normalizeRelativePath)(provenancePath)));
    const provenanceSummary = provenanceRecord === null ? null : provenanceRecord.sourceSummary;
    const summary = (0, release_notes_evidence_1.isReleaseNotesSourceSummaryLike)(directSummary)
        ? directSummary
        : (0, release_notes_evidence_1.isReleaseNotesSourceSummaryLike)(manifestSummary)
            ? manifestSummary
            : (0, release_notes_evidence_1.isReleaseNotesSourceSummaryLike)(provenanceSummary)
                ? provenanceSummary
                : null;
    if (summary === null) {
        return null;
    }
    const markerRecord = (0, release_notes_evidence_1.isRecord)(summary.marker) ? summary.marker : null;
    const markerSources = markerRecord !== null && Array.isArray(markerRecord.sources)
        ? markerRecord.sources
        : [];
    const previousMarkerPaths = markerSources.flatMap((source) => {
        if (!(0, release_notes_evidence_1.isRecord)(source) || typeof source.path !== 'string' || source.path.length === 0) {
            return [];
        }
        return [source.path];
    });
    return {
        selectedSources: normalizePlanningSources(summary.selectedSources),
        releasedSources: normalizePlanningSources(Array.isArray(summary.releasedSources) ? summary.releasedSources : summary.selectedSources),
        previousMarkerPaths,
        cumulative: Array.isArray(summary.releasedSources),
    };
}
function normalizePlanningSources(value) {
    return value.flatMap((source) => {
        if (!(0, release_notes_evidence_1.isRecord)(source) ||
            typeof source.path !== 'string' ||
            !['implementation-summary', 'milestone-reconciliation', 'explicit-release-metadata-include'].includes(String(source.kind))) {
            return [];
        }
        return [{
                kind: source.kind,
                path: (0, release_notes_evidence_1.normalizeRelativePath)(source.path),
                title: typeof source.title === 'string' ? source.title : null,
            }];
    });
}
function createSkippedReleaseNotesDraft(options) {
    return {
        status: 'skipped-dry-run',
        path: options.versionDirectoryRelative === null
            ? null
            : `${options.versionDirectoryRelative}/${release_notes_contracts_1.RELEASE_DOWNLOAD_BUNDLE_DIRECTORY}/${cli_constants_1.RELEASE_NOTES_FILENAME}`,
        sourceSummary: options.sourceSummary,
    };
}
function createNotApplicableReleaseNotesDraft() {
    return {
        status: 'not-applicable',
        path: null,
        sourceSummary: null,
    };
}
