"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.resolveMilestoneOverviewPath = resolveMilestoneOverviewPath;
exports.resolveOverviewPath = resolveOverviewPath;
exports.resolveTaskSlug = resolveTaskSlug;
exports.resolveTaskTitle = resolveTaskTitle;
exports.ensureDirectory = ensureDirectory;
exports.parseMilestoneOverview = parseMilestoneOverview;
exports.parseSliceOverview = parseSliceOverview;
exports.extractFrontMatter = extractFrontMatter;
exports.readTopLevelField = readTopLevelField;
exports.readUpstreamField = readUpstreamField;
exports.parseUpstreamSpecs = parseUpstreamSpecs;
exports.extractMarkdownSections = extractMarkdownSections;
exports.normalizeSectionText = normalizeSectionText;
exports.sectionBullets = sectionBullets;
exports.acceptanceCriterionIds = acceptanceCriterionIds;
exports.parseDeclaredTaskDescriptions = parseDeclaredTaskDescriptions;
exports.resolveTaskDescription = resolveTaskDescription;
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 front_matter_utils_1 = require("../front-matter-utils");
const governed_hierarchy_context_1 = require("../governed-hierarchy-context");
const planning_document_utils_1 = require("../planning-document-utils");
const runtime_acceptance_1 = require("../runtime-acceptance");
const acceptance_criterion_label_1 = require("../acceptance-criterion-label");
function resolveMilestoneOverviewPath(repositoryRoot, inputPath) {
    return resolveOverviewPath(repositoryRoot, inputPath, "--milestone-overview");
}
function resolveOverviewPath(repositoryRoot, inputPath, optionName) {
    try {
        if (optionName === "--milestone-overview") {
            return (0, paths_1.resolvePlanningOverviewInputPath)(repositoryRoot, {
                layer: "milestone",
                inputPath
            });
        }
        if (optionName === "--slice-overview") {
            return (0, paths_1.resolvePlanningOverviewInputPath)(repositoryRoot, {
                layer: "slice",
                inputPath
            });
        }
        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 ${optionName} path '${inputPath}'.`, [error instanceof Error ? error.message : String(error)]);
    }
}
function resolveTaskSlug(rawTaskSlug) {
    if ((0, paths_1.isCanonicalSlug)(rawTaskSlug)) {
        return rawTaskSlug;
    }
    const normalized = (0, paths_1.normalizeCanonicalSlug)(rawTaskSlug);
    if (normalized.kind === "canonical-slug") {
        return normalized.normalizedSlug;
    }
    throw (0, errors_1.createUsageError)(`Invalid task slug '${rawTaskSlug}'.`, [normalized.reason.message]);
}
function resolveTaskTitle(taskSlug, requestedTitle) {
    const trimmed = requestedTitle?.trim();
    if (trimmed !== undefined && trimmed !== "") {
        return trimmed;
    }
    return (0, front_matter_utils_1.toTitleCase)(taskSlug);
}
function ensureDirectory(directoryPath) {
    if (node_fs_1.default.existsSync(directoryPath)) {
        return "kept";
    }
    node_fs_1.default.mkdirSync(directoryPath, { recursive: true });
    return "created";
}
function parseMilestoneOverview(milestoneOverviewPath, providedText) {
    const fileText = providedText ?? node_fs_1.default.readFileSync(milestoneOverviewPath, "utf8");
    const sections = extractMarkdownSections(fileText);
    const frontMatter = extractFrontMatter(milestoneOverviewPath, fileText);
    const artifactType = readTopLevelField(frontMatter.lines, "artifact_type");
    if (artifactType !== "milestone_overview") {
        throw (0, errors_1.createUsageError)(`Parent overview '${(0, front_matter_utils_1.toRepositoryLikePath)(milestoneOverviewPath)}' must use artifact_type: milestone_overview.`);
    }
    const slice = readTopLevelField(frontMatter.lines, "slice");
    const phase = readTopLevelField(frontMatter.lines, "phase");
    const milestone = readTopLevelField(frontMatter.lines, "milestone");
    if (slice === undefined || slice.trim() === "") {
        throw (0, errors_1.createUsageError)(`Parent overview '${(0, front_matter_utils_1.toRepositoryLikePath)(milestoneOverviewPath)}' is missing required top-level field 'slice'.`);
    }
    if (phase === undefined || phase.trim() === "") {
        throw (0, errors_1.createUsageError)(`Parent overview '${(0, front_matter_utils_1.toRepositoryLikePath)(milestoneOverviewPath)}' is missing required top-level field 'phase'.`);
    }
    if (milestone === undefined || milestone.trim() === "") {
        throw (0, errors_1.createUsageError)(`Parent overview '${(0, front_matter_utils_1.toRepositoryLikePath)(milestoneOverviewPath)}' is missing required top-level field 'milestone'.`);
    }
    const planningDepth = readTopLevelField(frontMatter.lines, "planning_depth")?.trim() || "standard";
    const sliceOverviewPath = readUpstreamField(frontMatter.lines, "slice_overview");
    const phaseOverviewPath = readUpstreamField(frontMatter.lines, "phase_overview");
    if (sliceOverviewPath === undefined || sliceOverviewPath.trim() === "") {
        throw (0, errors_1.createUsageError)(`Parent overview '${(0, front_matter_utils_1.toRepositoryLikePath)(milestoneOverviewPath)}' is missing required upstream field 'slice_overview'.`);
    }
    if (phaseOverviewPath === undefined || phaseOverviewPath.trim() === "") {
        throw (0, errors_1.createUsageError)(`Parent overview '${(0, front_matter_utils_1.toRepositoryLikePath)(milestoneOverviewPath)}' is missing required upstream field 'phase_overview'.`);
    }
    const upstreamSpecs = parseUpstreamSpecs(frontMatter.lines, milestoneOverviewPath);
    const runtimeAcceptance = (0, runtime_acceptance_1.assertRuntimeAcceptanceInspection)((0, runtime_acceptance_1.inspectRuntimeAcceptance)({
        artifactPath: milestoneOverviewPath,
        artifactKind: "milestone",
        frontMatterLines: frontMatter.lines,
        markdownText: fileText
    }));
    const governedPolicy = (0, governed_hierarchy_context_1.readGovernedHierarchyPolicy)(frontMatter.lines);
    if (upstreamSpecs.length === 0) {
        throw (0, errors_1.createUsageError)(`Parent overview '${(0, front_matter_utils_1.toRepositoryLikePath)(milestoneOverviewPath)}' must include at least one upstream spec entry under upstream.specs.`);
    }
    return {
        slice: slice.trim(),
        phase: phase.trim(),
        milestone: milestone.trim(),
        planningDepth,
        sliceOverviewPath: sliceOverviewPath.trim(),
        phaseOverviewPath: phaseOverviewPath.trim(),
        upstreamSpecs,
        purpose: normalizeSectionText(sections.get("Purpose")),
        scope: sectionBullets(sections.get("Scope")),
        tasks: parseDeclaredTaskDescriptions(sections.get("Tasks") ?? []),
        acceptanceCriteria: sectionBullets(sections.get("Acceptance Criteria")),
        dependencies: sectionBullets(sections.get("Dependencies")),
        risks: sectionBullets(sections.get("Risks")),
        validationFocus: sectionBullets(sections.get("Validation Focus")),
        runtimeAcceptance,
        governedPolicy
    };
}
function parseSliceOverview(sliceOverviewPath) {
    const fileText = node_fs_1.default.readFileSync(sliceOverviewPath, "utf8");
    const frontMatter = extractFrontMatter(sliceOverviewPath, fileText);
    const artifactType = readTopLevelField(frontMatter.lines, "artifact_type");
    if (artifactType !== "slice_overview") {
        throw (0, errors_1.createUsageError)(`Parent overview '${(0, front_matter_utils_1.toRepositoryLikePath)(sliceOverviewPath)}' must use artifact_type: slice_overview.`);
    }
    const slice = readTopLevelField(frontMatter.lines, "slice");
    if (slice === undefined || slice.trim() === "") {
        throw (0, errors_1.createUsageError)(`Parent overview '${(0, front_matter_utils_1.toRepositoryLikePath)(sliceOverviewPath)}' is missing required top-level field 'slice'.`);
    }
    const planningDepth = readTopLevelField(frontMatter.lines, "planning_depth")?.trim() || "standard";
    const upstreamSpecs = parseUpstreamSpecs(frontMatter.lines, sliceOverviewPath);
    const governedPolicy = (0, governed_hierarchy_context_1.readGovernedHierarchyPolicy)(frontMatter.lines);
    if (upstreamSpecs.length === 0) {
        throw (0, errors_1.createUsageError)(`Parent overview '${(0, front_matter_utils_1.toRepositoryLikePath)(sliceOverviewPath)}' must include at least one upstream spec entry under upstream.specs.`);
    }
    return {
        slice: slice.trim(),
        planningDepth,
        upstreamSpecs,
        governedPolicy
    };
}
function extractFrontMatter(filePath, text) {
    const lines = text.split(/\r?\n/);
    if (lines[0] !== "---") {
        throw (0, errors_1.createUsageError)(`Parent overview '${(0, front_matter_utils_1.toRepositoryLikePath)(filePath)}' is missing YAML front matter.`);
    }
    let closingIndex = -1;
    for (let index = 1; index < lines.length; index += 1) {
        if (lines[index] === "---") {
            closingIndex = index;
            break;
        }
    }
    if (closingIndex === -1) {
        throw (0, errors_1.createUsageError)(`Parent overview '${(0, front_matter_utils_1.toRepositoryLikePath)(filePath)}' has malformed YAML front matter.`);
    }
    return {
        lines: lines.slice(1, closingIndex)
    };
}
function readTopLevelField(lines, key) {
    for (const line of lines) {
        if (/^\s/.test(line)) {
            continue;
        }
        const match = line.match(/^([A-Za-z0-9_]+):\s*(.*)$/);
        if (match === null) {
            continue;
        }
        if (match[1] === key) {
            return (0, front_matter_utils_1.parseScalar)(match[2]);
        }
    }
    return undefined;
}
function readUpstreamField(lines, key) {
    let inUpstream = false;
    for (const line of lines) {
        if (!inUpstream) {
            if (line.trim() === "upstream:") {
                inUpstream = true;
            }
            continue;
        }
        if (!/^\s/.test(line)) {
            break;
        }
        const match = line.match(/^\s{2}([A-Za-z0-9_]+):\s*(.*)$/);
        if (match !== null && match[1] === key) {
            return (0, front_matter_utils_1.parseScalar)(match[2]);
        }
    }
    return undefined;
}
function parseUpstreamSpecs(lines, filePath) {
    const entries = [];
    for (let index = 0; index < lines.length; index += 1) {
        const idMatch = lines[index].match(/^\s*-\s+id:\s*(.+)$/);
        if (idMatch === null) {
            continue;
        }
        const depthLine = lines[index + 1];
        const refLine = lines[index + 2];
        const sourceTypeLine = lines[index + 3];
        const depthMatch = depthLine?.match(/^\s+depth:\s*(.+)$/);
        const refMatch = refLine?.match(/^\s+ref:\s*(.+)$/);
        const sourceTypeMatch = sourceTypeLine?.match(/^\s+source_type:\s*(.+)$/);
        if (depthMatch === null || refMatch === null || sourceTypeMatch === null) {
            throw (0, errors_1.createUsageError)(`Parent overview '${(0, front_matter_utils_1.toRepositoryLikePath)(filePath)}' has malformed upstream.specs metadata near '${lines[index].trim()}'.`);
        }
        entries.push({
            id: (0, front_matter_utils_1.parseScalar)(idMatch[1]),
            depth: (0, front_matter_utils_1.parseScalar)(depthMatch[1]),
            ref: (0, front_matter_utils_1.parseScalar)(refMatch[1]),
            sourceType: (0, front_matter_utils_1.parseScalar)(sourceTypeMatch[1])
        });
        index += 3;
    }
    return entries;
}
function extractMarkdownSections(text) {
    const lines = text.split(/\r?\n/);
    const sections = new Map();
    let currentSection;
    for (const line of lines) {
        const headingMatch = line.match(/^##\s+(.+?)\s*$/);
        if (headingMatch !== null) {
            currentSection = headingMatch[1];
            sections.set(currentSection, []);
            continue;
        }
        if (line.startsWith("# ")) {
            currentSection = undefined;
            continue;
        }
        if (currentSection !== undefined) {
            sections.get(currentSection)?.push(line);
        }
    }
    return sections;
}
function normalizeSectionText(lines) {
    return (lines ?? [])
        .map((line) => line.trim())
        .filter((line) => line !== "")
        .join(" ");
}
function sectionBullets(lines) {
    return (0, planning_document_utils_1.parseMarkdownListItems)(lines);
}
function acceptanceCriterionIds(acceptanceCriteria) {
    return acceptanceCriteria.flatMap((criterion) => {
        const criterionId = (0, acceptance_criterion_label_1.normalizeAcceptanceCriterionId)(criterion);
        return criterionId === null ? [] : [criterionId];
    });
}
function parseDeclaredTaskDescriptions(lines) {
    const descriptions = new Map();
    for (const declaration of (0, planning_document_utils_1.parseDeclaredChildSlugBullets)(lines)) {
        descriptions.set(declaration.slug, declaration.description);
    }
    return descriptions;
}
function resolveTaskDescription(taskSlug, requestedDescription, taskDescriptions) {
    const trimmed = requestedDescription?.trim();
    if (trimmed !== undefined && trimmed !== "") {
        return trimmed;
    }
    return taskDescriptions.get(taskSlug) ?? "";
}
