"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.escapeRegExp = escapeRegExp;
exports.resolveRepositoryPath = resolveRepositoryPath;
exports.parseMarkdownDocument = parseMarkdownDocument;
exports.collectDuplicateImplementationSummaryPaths = collectDuplicateImplementationSummaryPaths;
exports.pathOverlapsAnyTarget = pathOverlapsAnyTarget;
exports.pathsOverlap = pathsOverlap;
exports.hasConcreteDeviationJustification = hasConcreteDeviationJustification;
exports.hasRuntimeTargetReplacementDeviation = hasRuntimeTargetReplacementDeviation;
exports.normalizePathEvidenceText = normalizePathEvidenceText;
exports.normalizeImplementationSummaryChangedPathsForBuild = normalizeImplementationSummaryChangedPathsForBuild;
exports.buildImplementationSummaryChangedPathAuthoring = buildImplementationSummaryChangedPathAuthoring;
exports.renderChangedPathAuthoringRecovery = renderChangedPathAuthoringRecovery;
exports.uniqueSorted = uniqueSorted;
// Responsibility-focused implementation extracted from the public compatibility facade.
const node_fs_1 = __importDefault(require("node:fs"));
const node_path_1 = __importDefault(require("node:path"));
const errors_1 = require("../../errors");
const paths_1 = require("../../paths");
const sandbox_contract_1 = require("../../paths/sandbox-contract");
const front_matter_utils_1 = require("../front-matter-utils");
const planning_artifact_document_1 = require("../planning-artifact-document");
const selector_evidence_1 = require("../reconciliation/selector-evidence");
const semantic_placeholder_1 = require("../semantic-placeholder");
const task_cycle_runtime_attribution_1 = require("../task-cycle-runtime-attribution");
const evidence_1 = require("./evidence");
function escapeRegExp(value) {
    return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
function resolveRepositoryPath(repositoryRoot, inputPath, label) {
    try {
        const parsed = (0, paths_1.parseRepositoryRelativePath)(inputPath);
        return {
            relative: parsed.normalizedPath,
            absolute: node_path_1.default.join(repositoryRoot, parsed.normalizedPath)
        };
    }
    catch (error) {
        throw (0, errors_1.createUsageError)(`Invalid --${label.replace(/ /g, "-")} path '${inputPath}'.`, [error instanceof Error ? error.message : String(error)]);
    }
}
function parseMarkdownDocument(filePath, text) {
    const document = (0, planning_artifact_document_1.parsePlanningArtifactDocument)(text);
    if (!document.hasFrontMatter) {
        throw (0, errors_1.createUsageError)(`Artifact '${filePath}' is missing YAML front matter.`);
    }
    if (document.diagnostics.some((diagnostic) => diagnostic.code === "unterminated-front-matter")) {
        throw (0, errors_1.createUsageError)(`Artifact '${filePath}' has malformed YAML front matter.`);
    }
    const sections = new Map();
    for (const section of document.sections) {
        sections.set(section.heading, (0, evidence_1.trimSectionContent)(section.contentText.split(/\r?\n/)));
    }
    const title = document.bodyText.match(/^#\s+(.+)$/m)?.[1]?.trim() ?? null;
    return {
        frontMatterLines: [...document.frontMatterLines],
        sections,
        title,
        rawText: text
    };
}
function collectDuplicateImplementationSummaryPaths(repositoryRoot, taskDefinitionPath, canonicalImplementationSummaryPath) {
    const taskDirectory = node_path_1.default.dirname(taskDefinitionPath);
    const absoluteTaskDirectory = node_path_1.default.join(repositoryRoot, taskDirectory);
    const duplicatePaths = [];
    if (!node_fs_1.default.existsSync(absoluteTaskDirectory)) {
        return duplicatePaths;
    }
    const visit = (absoluteDirectory) => {
        const entries = node_fs_1.default.readdirSync(absoluteDirectory, { withFileTypes: true });
        for (const entry of entries) {
            const absoluteEntryPath = node_path_1.default.join(absoluteDirectory, entry.name);
            if (entry.isDirectory()) {
                visit(absoluteEntryPath);
                continue;
            }
            if (!entry.isFile() || !entry.name.endsWith(".md")) {
                continue;
            }
            const relativeEntryPath = (0, front_matter_utils_1.toRepositoryLikePath)(node_path_1.default.relative(repositoryRoot, absoluteEntryPath));
            if (relativeEntryPath === canonicalImplementationSummaryPath) {
                continue;
            }
            let entryText;
            try {
                entryText = node_fs_1.default.readFileSync(absoluteEntryPath, "utf8");
            }
            catch {
                continue;
            }
            let entryDocument;
            try {
                entryDocument = parseMarkdownDocument(relativeEntryPath, entryText);
            }
            catch {
                continue;
            }
            const artifactType = (0, selector_evidence_1.readTopLevelField)(entryDocument.frontMatterLines, "artifact_type")?.trim();
            if (artifactType === "implementation_summary") {
                duplicatePaths.push(relativeEntryPath);
            }
        }
    };
    visit(absoluteTaskDirectory);
    return duplicatePaths.sort((a, b) => a.localeCompare(b, "en"));
}
function pathOverlapsAnyTarget(changedPath, targetPaths) {
    return targetPaths.some((targetPath) => pathsOverlap(changedPath, targetPath));
}
function pathsOverlap(leftPath, rightPath) {
    return leftPath === rightPath
        || leftPath.startsWith(`${rightPath}/`)
        || rightPath.startsWith(`${leftPath}/`);
}
function hasConcreteDeviationJustification(sectionText) {
    if (sectionText === undefined || (0, semantic_placeholder_1.hasSemanticPlaceholderContent)(sectionText)) {
        return false;
    }
    const normalized = sectionText.trim().replace(/^[-*]\s+/gm, "").trim();
    return normalized !== ""
        && !/^(none|none\.|no deviations\.?|no deviation\.?|not applicable\.?|n\/a\.?)$/i.test(normalized);
}
function hasRuntimeTargetReplacementDeviation(sectionText, declaredTargetPath, changedPath) {
    if (!hasConcreteDeviationJustification(sectionText)) {
        return false;
    }
    const normalizedSectionText = normalizePathEvidenceText(sectionText ?? "");
    return normalizedSectionText.includes(declaredTargetPath)
        && normalizedSectionText.includes(changedPath);
}
function normalizePathEvidenceText(text) {
    return text
        .replace(/\\/g, "/")
        .replace(/`/g, "")
        .trim();
}
function normalizeImplementationSummaryChangedPathsForBuild(sectionText, authoring) {
    if ((0, semantic_placeholder_1.hasSemanticPlaceholderContent)(sectionText)) {
        return sectionText;
    }
    const evidence = (0, evidence_1.extractSummaryChangedPathEvidence)(sectionText);
    const rejected = evidence.filter((entry) => entry.state !== "path");
    if (rejected.length > 0) {
        throw (0, errors_1.createUsageError)("Implementation summary build rejected unsupported Changed Paths evidence before writing.", [
            ...rejected.map((entry) => entry.message),
            ...renderChangedPathAuthoringRecovery(authoring)
        ]);
    }
    const canonicalPaths = [...new Set(evidence
            .filter((entry) => entry.path !== undefined)
            .map((entry) => entry.path))];
    if (canonicalPaths.length === 0) {
        throw (0, errors_1.createUsageError)("Implementation summary build rejected Changed Paths evidence without a concrete repository-relative path.", [
            "Use one top-level bullet per path in the form '- `repository/relative/path`'.",
            ...renderChangedPathAuthoringRecovery(authoring)
        ]);
    }
    return canonicalPaths.map((changedPath) => `- \`${changedPath}\``).join("\n");
}
function buildImplementationSummaryChangedPathAuthoring(repositoryRoot, options) {
    if (options.summaryMarkdownText === null) {
        return {
            candidatePaths: [],
            renderedMarkdown: "",
            excludedPaths: [],
            attributionAvailable: false
        };
    }
    const attribution = (0, task_cycle_runtime_attribution_1.deriveTaskAttemptPathAttribution)(repositoryRoot, {
        taskDefinitionPath: options.taskDefinitionPath,
        taskMarkdownText: options.taskMarkdownText,
        summaryMarkdownText: options.summaryMarkdownText
    });
    if (attribution === null) {
        return {
            candidatePaths: [],
            renderedMarkdown: "",
            excludedPaths: [],
            attributionAvailable: false
        };
    }
    const candidateClassifications = new Set([
        "task_associated",
        "new_untracked",
        "renamed",
        "adopted_pre_staged"
    ]);
    const candidatePaths = uniqueSorted(attribution.classifications
        .filter((entry) => entry.declared
        && !entry.protectedPath
        && candidateClassifications.has(entry.classification))
        .map((entry) => entry.path));
    const candidatePathSet = new Set(candidatePaths);
    const excludedPaths = attribution.classifications
        .filter((entry) => !candidatePathSet.has(entry.path)
        && !isManagedLifecycleRunPath(entry.path))
        .map((entry) => ({
        path: entry.path,
        reason: entry.protectedPath
            ? "protected-lifecycle-path"
            : !entry.declared || entry.classification === "post_baseline_out_of_scope"
                ? "outside-declared-attempt-scope"
                : entry.classification === "accepted_predecessor"
                    ? "accepted-predecessor-evidence-only"
                    : entry.classification === "pre_existing"
                        ? "pre-existing-not-adopted"
                        : "uncertain-attribution"
    }))
        .sort((left, right) => left.path.localeCompare(right.path, "en"));
    return {
        candidatePaths,
        renderedMarkdown: candidatePaths.map((candidatePath) => `- \`${candidatePath}\``).join("\n"),
        excludedPaths,
        attributionAvailable: true
    };
}
function renderChangedPathAuthoringRecovery(authoring) {
    const lines = authoring.candidatePaths.length === 0
        ? [authoring.attributionAvailable
                ? "No current-attempt eligible Changed Paths candidates were detected."
                : "Changed Paths candidates are unavailable until the current attempt has a runtime-attribution baseline."]
        : [
            `Current-attempt candidatePaths: ${JSON.stringify(authoring.candidatePaths)}`,
            `Paste this path-only Markdown:\n${authoring.renderedMarkdown}`
        ];
    const maximumExcludedPathDetails = 8;
    const renderedExclusions = authoring.excludedPaths
        .slice(0, maximumExcludedPathDetails)
        .map((entry) => `Excluded '${entry.path}' from Changed Paths candidates: ${entry.reason}.`);
    const omittedExclusionCount = authoring.excludedPaths.length - renderedExclusions.length;
    if (omittedExclusionCount <= 0)
        return [...lines, ...renderedExclusions];
    const exclusionCounts = [...authoring.excludedPaths.reduce((counts, entry) => {
            counts.set(entry.reason, (counts.get(entry.reason) ?? 0) + 1);
            return counts;
        }, new Map())]
        .sort(([left], [right]) => left.localeCompare(right, "en"))
        .map(([reason, count]) => `${reason}=${count}`)
        .join(", ");
    return [
        ...lines,
        `Excluded path totals by reason: ${exclusionCounts}.`,
        ...renderedExclusions,
        `Omitted ${omittedExclusionCount} additional excluded paths from this recovery message. The complete list remains available as changedPathAuthoring.excludedPaths in a successful JSON build response.`
    ];
}
function isManagedLifecycleRunPath(candidatePath) {
    return (0, sandbox_contract_1.isSandboxRunDirectoryPath)(candidatePath) || (0, sandbox_contract_1.isSandboxRunContentPath)(candidatePath);
}
function uniqueSorted(values) {
    return [...new Set(values)].sort((left, right) => left.localeCompare(right, "en"));
}
