export function normalizeRequirementName(name) {
    return name.trim();
}
const REQUIREMENT_HEADER_REGEX = /^###\s*Requirement:\s*(.+)\s*$/;
/**
 * Extracts the Requirements section from a spec file and parses requirement blocks.
 */
export function extractRequirementsSection(content) {
    const normalized = normalizeLineEndings(content);
    const lines = normalized.split('\n');
    const reqHeaderIndex = lines.findIndex(l => /^##\s+Requirements\s*$/i.test(l));
    if (reqHeaderIndex === -1) {
        // No requirements section; create an empty one at the end
        const before = content.trimEnd();
        const headerLine = '## Requirements';
        return {
            before: before ? before + '\n\n' : '',
            headerLine,
            preamble: '',
            bodyBlocks: [],
            after: '\n',
        };
    }
    // Find end of this section: next line that starts with '## ' at same or higher level
    let endIndex = lines.length;
    for (let i = reqHeaderIndex + 1; i < lines.length; i++) {
        if (/^##\s+/.test(lines[i])) {
            endIndex = i;
            break;
        }
    }
    const before = lines.slice(0, reqHeaderIndex).join('\n');
    const headerLine = lines[reqHeaderIndex];
    const sectionBodyLines = lines.slice(reqHeaderIndex + 1, endIndex);
    // Parse requirement blocks within section body
    const blocks = [];
    let cursor = 0;
    let preambleLines = [];
    // Collect preamble lines until first requirement header
    while (cursor < sectionBodyLines.length && !/^###\s+Requirement:/.test(sectionBodyLines[cursor])) {
        preambleLines.push(sectionBodyLines[cursor]);
        cursor++;
    }
    while (cursor < sectionBodyLines.length) {
        const headerStart = cursor;
        const headerLineCandidate = sectionBodyLines[cursor];
        const headerMatch = headerLineCandidate.match(REQUIREMENT_HEADER_REGEX);
        if (!headerMatch) {
            // Not a requirement header; skip line defensively
            cursor++;
            continue;
        }
        const name = normalizeRequirementName(headerMatch[1]);
        cursor++;
        // Gather lines until next requirement header or end of section
        const bodyLines = [headerLineCandidate];
        while (cursor < sectionBodyLines.length && !/^###\s+Requirement:/.test(sectionBodyLines[cursor]) && !/^##\s+/.test(sectionBodyLines[cursor])) {
            bodyLines.push(sectionBodyLines[cursor]);
            cursor++;
        }
        const raw = bodyLines.join('\n').trimEnd();
        blocks.push({ headerLine: headerLineCandidate, name, raw });
    }
    const after = lines.slice(endIndex).join('\n');
    const preamble = preambleLines.join('\n').trimEnd();
    return {
        before: before.trimEnd() ? before + '\n' : before,
        headerLine,
        preamble,
        bodyBlocks: blocks,
        after: after.startsWith('\n') ? after : '\n' + after,
    };
}
function normalizeLineEndings(content) {
    return content.replace(/\r\n?/g, '\n');
}
/**
 * Parse a delta-formatted spec change file content into a DeltaPlan with raw blocks.
 */
export function parseDeltaSpec(content) {
    const normalized = normalizeLineEndings(content);
    const sections = splitTopLevelSections(normalized);
    const addedLookup = getSectionCaseInsensitive(sections, 'ADDED Requirements');
    const modifiedLookup = getSectionCaseInsensitive(sections, 'MODIFIED Requirements');
    const removedLookup = getSectionCaseInsensitive(sections, 'REMOVED Requirements');
    const renamedLookup = getSectionCaseInsensitive(sections, 'RENAMED Requirements');
    const added = parseRequirementBlocksFromSection(addedLookup.body);
    const modified = parseRequirementBlocksFromSection(modifiedLookup.body);
    const removedNames = parseRemovedNames(removedLookup.body);
    const renamedPairs = parseRenamedPairs(renamedLookup.body);
    return {
        added,
        modified,
        removed: removedNames,
        renamed: renamedPairs,
        sectionPresence: {
            added: addedLookup.found,
            modified: modifiedLookup.found,
            removed: removedLookup.found,
            renamed: renamedLookup.found,
        },
    };
}
function splitTopLevelSections(content) {
    const lines = content.split('\n');
    const result = {};
    const indices = [];
    for (let i = 0; i < lines.length; i++) {
        const m = lines[i].match(/^(##)\s+(.+)$/);
        if (m) {
            const level = m[1].length; // only care for '##'
            indices.push({ title: m[2].trim(), index: i, level });
        }
    }
    for (let i = 0; i < indices.length; i++) {
        const current = indices[i];
        const next = indices[i + 1];
        const body = lines.slice(current.index + 1, next ? next.index : lines.length).join('\n');
        result[current.title] = body;
    }
    return result;
}
function getSectionCaseInsensitive(sections, desired) {
    const target = desired.toLowerCase();
    for (const [title, body] of Object.entries(sections)) {
        if (title.toLowerCase() === target)
            return { body, found: true };
    }
    return { body: '', found: false };
}
function parseRequirementBlocksFromSection(sectionBody) {
    if (!sectionBody)
        return [];
    const lines = normalizeLineEndings(sectionBody).split('\n');
    const blocks = [];
    let i = 0;
    while (i < lines.length) {
        // Seek next requirement header
        while (i < lines.length && !/^###\s+Requirement:/.test(lines[i]))
            i++;
        if (i >= lines.length)
            break;
        const headerLine = lines[i];
        const m = headerLine.match(REQUIREMENT_HEADER_REGEX);
        if (!m) {
            i++;
            continue;
        }
        const name = normalizeRequirementName(m[1]);
        const buf = [headerLine];
        i++;
        while (i < lines.length && !/^###\s+Requirement:/.test(lines[i]) && !/^##\s+/.test(lines[i])) {
            buf.push(lines[i]);
            i++;
        }
        blocks.push({ headerLine, name, raw: buf.join('\n').trimEnd() });
    }
    return blocks;
}
function parseRemovedNames(sectionBody) {
    if (!sectionBody)
        return [];
    const names = [];
    const lines = normalizeLineEndings(sectionBody).split('\n');
    for (const line of lines) {
        const m = line.match(REQUIREMENT_HEADER_REGEX);
        if (m) {
            names.push(normalizeRequirementName(m[1]));
            continue;
        }
        // Also support bullet list of headers
        const bullet = line.match(/^\s*-\s*`?###\s*Requirement:\s*(.+?)`?\s*$/);
        if (bullet) {
            names.push(normalizeRequirementName(bullet[1]));
        }
    }
    return names;
}
function parseRenamedPairs(sectionBody) {
    if (!sectionBody)
        return [];
    const pairs = [];
    const lines = normalizeLineEndings(sectionBody).split('\n');
    let current = {};
    for (const line of lines) {
        const fromMatch = line.match(/^\s*-?\s*FROM:\s*`?###\s*Requirement:\s*(.+?)`?\s*$/);
        const toMatch = line.match(/^\s*-?\s*TO:\s*`?###\s*Requirement:\s*(.+?)`?\s*$/);
        if (fromMatch) {
            current.from = normalizeRequirementName(fromMatch[1]);
        }
        else if (toMatch) {
            current.to = normalizeRequirementName(toMatch[1]);
            if (current.from && current.to) {
                pairs.push({ from: current.from, to: current.to });
                current = {};
            }
        }
    }
    return pairs;
}
//# sourceMappingURL=requirement-blocks.js.map