"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.renderBaselineBlock = renderBaselineBlock;
exports.renderSummaryBlock = renderSummaryBlock;
exports.renderScalarList = renderScalarList;
exports.readTargetList = readTargetList;
exports.targetFromRecord = targetFromRecord;
exports.readAdoptionList = readAdoptionList;
exports.readAcceptedPredecessorList = readAcceptedPredecessorList;
exports.acceptedPredecessorFromRecord = acceptedPredecessorFromRecord;
exports.lineStartsNewSummaryField = lineStartsNewSummaryField;
exports.readScalarList = readScalarList;
exports.readScalar = readScalar;
exports.readFrontMatterBlock = readFrontMatterBlock;
exports.replaceFrontMatterBlock = replaceFrontMatterBlock;
exports.removeFrontMatterBlock = removeFrontMatterBlock;
const errors_1 = require("../../errors");
const planning_document_utils_1 = require("../planning-document-utils");
const contracts_1 = require("./contracts");
const repository_support_1 = require("./repository-support");
function renderBaselineBlock(baseline) {
    return [
        `${contracts_1.BASELINE_BLOCK}:`,
        `  schema_version: ${baseline.schemaVersion}`,
        `  baseline_id: ${(0, repository_support_1.quote)(baseline.baselineId)}`,
        `  task_cycle_id: ${(0, repository_support_1.quote)(baseline.taskCycleId)}`,
        `  checkpoint_id: ${(0, repository_support_1.quote)(baseline.checkpointId)}`,
        "  captured_after_readiness: true",
        "  captured_before_implementation_writes: true",
        `  source_revision: ${(0, repository_support_1.quote)(baseline.sourceRevision)}`,
        `  repository_dirty_state: ${(0, repository_support_1.quote)(baseline.repositoryDirtyState)}`,
        `  cli_runtime_source: ${(0, repository_support_1.quote)(baseline.cliRuntimeSource)}`,
        `  cli_build_identity: ${(0, repository_support_1.quote)(baseline.cliBuildIdentity)}`,
        ...(baseline.schemaVersion === 2 ? [
            `  captured_by: ${(0, repository_support_1.quote)(baseline.capturedBy ?? "")}`,
            `  captured_at: ${(0, repository_support_1.quote)(baseline.capturedAt ?? "")}`,
            `  working_tree_digest: ${(0, repository_support_1.quote)(baseline.workingTreeDigest ?? "")}`,
            `  status_digest: ${(0, repository_support_1.quote)(baseline.statusDigest ?? "")}`,
            `  observations_complete: ${baseline.observationsComplete}`,
            `  contract_impact_fingerprint: ${baseline.contractImpactFingerprint == null ? "null" : (0, repository_support_1.quote)(baseline.contractImpactFingerprint)}`
        ] : []),
        "  declared_targets:",
        ...baseline.declaredTargets.flatMap((target) => [
            `    - path: ${(0, repository_support_1.quote)(target.path)}`,
            `      exists: ${target.exists}`,
            `      kind: ${(0, repository_support_1.quote)(target.kind)}`,
            `      content_sha256: ${target.contentSha256 === null ? "null" : (0, repository_support_1.quote)(target.contentSha256)}`,
            `      repository_visibility: ${(0, repository_support_1.quote)(target.repositoryVisibility)}`,
            `      ignore_rule: ${target.ignoreRule === null ? "null" : (0, repository_support_1.quote)(target.ignoreRule)}`,
            `      dirty: ${target.dirty}`,
            `      pre_existing_classification: ${(0, repository_support_1.quote)(target.preExistingClassification)}`,
            `      adoption_rationale: ${(0, repository_support_1.quote)(target.adoptionRationale)}`,
            `      accepted_predecessor_task: ${target.acceptedPredecessor == null ? "null" : (0, repository_support_1.quote)(target.acceptedPredecessor.taskId)}`,
            `      accepted_predecessor_task_definition: ${target.acceptedPredecessor == null ? "null" : (0, repository_support_1.quote)(target.acceptedPredecessor.taskDefinitionPath)}`,
            `      accepted_predecessor_summary: ${target.acceptedPredecessor == null ? "null" : (0, repository_support_1.quote)(target.acceptedPredecessor.implementationSummaryPath)}`,
            `      accepted_predecessor_attempt: ${target.acceptedPredecessor == null ? "null" : (0, repository_support_1.quote)(target.acceptedPredecessor.attemptId)}`,
            `      accepted_predecessor_review_receipt: ${target.acceptedPredecessor == null ? "null" : (0, repository_support_1.quote)(target.acceptedPredecessor.reviewReceiptId)}`,
            `      accepted_predecessor_summary_revision: ${target.acceptedPredecessor == null ? "null" : (0, repository_support_1.quote)(target.acceptedPredecessor.implementationSummaryRevision)}`,
            `      accepted_predecessor_path_digest: ${target.acceptedPredecessor == null ? "null" : (0, repository_support_1.quote)(target.acceptedPredecessor.pathDigest)}`,
            `      accepted_predecessor_source_revision: ${target.acceptedPredecessor == null ? "null" : (0, repository_support_1.quote)(target.acceptedPredecessor.sourceRevision)}`
        ])
    ];
}
function renderSummaryBlock(evidence) {
    return [
        `${contracts_1.SUMMARY_BLOCK}:`,
        "  schema_version: 1",
        `  baseline_id: ${(0, repository_support_1.quote)(evidence.baselineId)}`,
        `  task_cycle_id: ${(0, repository_support_1.quote)(evidence.taskCycleId)}`,
        `  checkpoint_id: ${(0, repository_support_1.quote)(evidence.checkpointId)}`,
        `  source_revision: ${(0, repository_support_1.quote)(evidence.sourceRevision)}`,
        `  current_revision: ${(0, repository_support_1.quote)(evidence.currentRevision)}`,
        ...renderScalarList("fresh_runtime_paths", evidence.freshRuntimePaths),
        ...renderScalarList("executable_validation", evidence.executableValidation),
        ...renderScalarList("satisfied_criterion_ids", evidence.satisfiedCriterionIds),
        "  adopted_paths:",
        ...(evidence.adoptedPaths.length === 0
            ? ["    []"]
            : evidence.adoptedPaths.flatMap((entry) => [
                `    - path: ${(0, repository_support_1.quote)(entry.path)}`,
                `      rationale: ${(0, repository_support_1.quote)(entry.rationale)}`
            ])),
        "  accepted_predecessor_paths:",
        ...(evidence.acceptedPredecessorPaths.length === 0
            ? ["    []"]
            : evidence.acceptedPredecessorPaths.flatMap((entry) => [
                `    - path: ${(0, repository_support_1.quote)(entry.path)}`,
                `      predecessor_task: ${(0, repository_support_1.quote)(entry.taskId)}`,
                `      task_definition: ${(0, repository_support_1.quote)(entry.taskDefinitionPath)}`,
                `      implementation_summary: ${(0, repository_support_1.quote)(entry.implementationSummaryPath)}`,
                `      attempt_id: ${(0, repository_support_1.quote)(entry.attemptId)}`,
                `      review_receipt_id: ${(0, repository_support_1.quote)(entry.reviewReceiptId)}`,
                `      implementation_summary_revision: ${(0, repository_support_1.quote)(entry.implementationSummaryRevision)}`,
                `      path_digest: ${(0, repository_support_1.quote)(entry.pathDigest)}`,
                `      source_revision: ${(0, repository_support_1.quote)(entry.sourceRevision)}`
            ])),
        ...renderScalarList("ineligible_paths", evidence.ineligiblePaths)
    ];
}
function renderScalarList(key, values) {
    return values.length === 0
        ? [`  ${key}: []`]
        : [`  ${key}:`, ...values.map((value) => `    - ${(0, repository_support_1.quote)(value)}`)];
}
function readTargetList(lines) {
    const start = lines.findIndex((line) => line === "  declared_targets:");
    if (start === -1)
        return [];
    const targets = [];
    let current = null;
    for (let index = start + 1; index < lines.length; index += 1) {
        const line = lines[index];
        const first = line.match(/^ {4}- path:\s*(.+)$/);
        if (first !== null) {
            if (current !== null)
                targets.push(targetFromRecord(current));
            current = { path: (0, planning_document_utils_1.parseScalar)(first[1]) };
            continue;
        }
        const field = line.match(/^ {6}([a-z0-9_]+):\s*(.*)$/);
        if (field !== null && current !== null) {
            current[field[1]] = (0, planning_document_utils_1.parseScalar)(field[2]);
            continue;
        }
        if (line.trim() !== "")
            break;
    }
    if (current !== null)
        targets.push(targetFromRecord(current));
    return targets;
}
function targetFromRecord(record) {
    const acceptedPredecessor = record.accepted_predecessor_task === undefined
        || record.accepted_predecessor_task === "null"
        ? null
        : {
            taskId: record.accepted_predecessor_task,
            taskDefinitionPath: record.accepted_predecessor_task_definition ?? "",
            implementationSummaryPath: record.accepted_predecessor_summary ?? "",
            attemptId: record.accepted_predecessor_attempt ?? "",
            reviewReceiptId: record.accepted_predecessor_review_receipt ?? "",
            implementationSummaryRevision: record.accepted_predecessor_summary_revision ?? "",
            pathDigest: record.accepted_predecessor_path_digest ?? "",
            sourceRevision: record.accepted_predecessor_source_revision ?? ""
        };
    return {
        path: record.path ?? "",
        exists: record.exists === "true",
        kind: (record.kind ?? "absent"),
        contentSha256: record.content_sha256 === "null" || record.content_sha256 === undefined
            ? null
            : record.content_sha256,
        repositoryVisibility: (record.repository_visibility
            ?? (record.exists === "true" ? "tracked" : "absent")),
        ignoreRule: record.ignore_rule === "null" || record.ignore_rule === undefined ? null : record.ignore_rule,
        dirty: record.dirty === "true",
        preExistingClassification: (record.pre_existing_classification ?? ""),
        adoptionRationale: record.adoption_rationale ?? "",
        acceptedPredecessor
    };
}
function readAdoptionList(lines) {
    const start = lines.findIndex((line) => line === "  adopted_paths:");
    if (start === -1 || lines[start + 1]?.trim() === "[]")
        return [];
    const entries = [];
    for (let index = start + 1; index < lines.length; index += 1) {
        const match = lines[index].match(/^ {4}- path:\s*(.+)$/);
        if (match === null) {
            if (lines[index].trim() !== "")
                break;
            continue;
        }
        const rationale = lines[index + 1]?.match(/^ {6}rationale:\s*(.*)$/);
        entries.push({ path: (0, planning_document_utils_1.parseScalar)(match[1]), rationale: (0, planning_document_utils_1.parseScalar)(rationale?.[1] ?? "") });
        index += 1;
    }
    return entries;
}
function readAcceptedPredecessorList(lines) {
    const start = lines.findIndex((line) => line === "  accepted_predecessor_paths:");
    if (start === -1 || lines[start + 1]?.trim() === "[]")
        return [];
    const entries = [];
    let current = null;
    for (let index = start + 1; index < lines.length; index += 1) {
        const first = lines[index].match(/^ {4}- path:\s*(.+)$/);
        if (first !== null) {
            if (current !== null)
                entries.push(acceptedPredecessorFromRecord(current));
            current = { path: (0, planning_document_utils_1.parseScalar)(first[1]) };
            continue;
        }
        const field = lines[index].match(/^ {6}([a-z0-9_]+):\s*(.*)$/);
        if (field !== null && current !== null) {
            current[field[1]] = (0, planning_document_utils_1.parseScalar)(field[2]);
            continue;
        }
        if (lineStartsNewSummaryField(lines[index]))
            break;
    }
    if (current !== null)
        entries.push(acceptedPredecessorFromRecord(current));
    return entries;
}
function acceptedPredecessorFromRecord(record) {
    return {
        path: record.path ?? "",
        taskId: record.predecessor_task ?? "",
        taskDefinitionPath: record.task_definition ?? "",
        implementationSummaryPath: record.implementation_summary ?? "",
        attemptId: record.attempt_id ?? "",
        reviewReceiptId: record.review_receipt_id ?? "",
        implementationSummaryRevision: record.implementation_summary_revision ?? "",
        pathDigest: record.path_digest ?? "",
        sourceRevision: record.source_revision ?? ""
    };
}
function lineStartsNewSummaryField(line) {
    return /^ {2}[a-z0-9_]+:/.test(line);
}
function readScalarList(lines, key) {
    const inline = lines.find((line) => line.startsWith(`  ${key}:`));
    if (inline === undefined)
        return [];
    if (inline.trim() === `${key}: []`)
        return [];
    const start = lines.indexOf(inline);
    const values = [];
    for (let index = start + 1; index < lines.length; index += 1) {
        const match = lines[index].match(/^ {4}-\s+(.+)$/);
        if (match === null)
            break;
        values.push((0, planning_document_utils_1.parseScalar)(match[1]));
    }
    return values;
}
function readScalar(lines, key) {
    const match = lines.find((line) => line.startsWith(`  ${key}:`))?.match(/^ {2}[a-z_]+:\s*(.*)$/);
    return match === undefined || match === null ? undefined : (0, planning_document_utils_1.parseScalar)(match[1]);
}
function readFrontMatterBlock(lines, name) {
    const start = lines.findIndex((line) => line === `${name}:`);
    if (start === -1)
        return null;
    let end = lines.length;
    for (let index = start + 1; index < lines.length; index += 1) {
        if (lines[index] !== "" && !/^\s/.test(lines[index])) {
            end = index;
            break;
        }
    }
    return lines.slice(start + 1, end);
}
function replaceFrontMatterBlock(markdownText, name, blockLines) {
    const lines = markdownText.split(/\r?\n/);
    const closing = lines.findIndex((line, index) => index > 0 && line === "---");
    if (lines[0] !== "---" || closing === -1)
        throw (0, errors_1.createUsageError)("Planning artifact front matter is malformed.");
    const existing = lines.findIndex((line, index) => index > 0 && index < closing && line === `${name}:`);
    if (existing !== -1) {
        let end = closing;
        for (let index = existing + 1; index < closing; index += 1) {
            if (lines[index] !== "" && !/^\s/.test(lines[index])) {
                end = index;
                break;
            }
        }
        lines.splice(existing, end - existing, ...blockLines);
        return lines.join("\n");
    }
    const upstream = lines.findIndex((line, index) => index > 0 && index < closing && line === "upstream:");
    lines.splice(upstream === -1 ? closing : upstream, 0, ...blockLines);
    return lines.join("\n");
}
function removeFrontMatterBlock(markdownText, name) {
    const lines = markdownText.split(/\r?\n/);
    const closing = lines.findIndex((line, index) => index > 0 && line === "---");
    const start = lines.findIndex((line, index) => index > 0 && index < closing && line === `${name}:`);
    if (start === -1)
        return markdownText;
    let end = closing;
    for (let index = start + 1; index < closing; index += 1) {
        if (lines[index] !== "" && !/^\s/.test(lines[index])) {
            end = index;
            break;
        }
    }
    lines.splice(start, end - start);
    return lines.join("\n");
}
