"use strict";
/**
 * test_story_parser — v1.12.0 StoryParser regression suite.
 *
 * Parses every real *.story.md and epic.md under docs/stories/ and
 * asserts the parser extracts StoryId/Epic/Status, at least one
 * acceptance criterion when the section exists, and never throws on
 * the real corpus. Also tests constructed bad inputs.
 *
 * Run via: `npm run test:story-parser` (compiles + executes dist/).
 *
 * Pattern: throws or process.exit(1) on failure; prints
 * TEST_STORY_PARSER_OK on full pass.
 */
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const StoryParser_1 = require("./orchestrator/story/StoryParser");
const StorySchema_1 = require("./orchestrator/story/StorySchema");
function assert(cond, msg) {
    if (!cond)
        throw new Error(`assertion failed: ${msg}`);
}
function walk(dir, out) {
    if (!fs.existsSync(dir))
        return;
    for (const name of fs.readdirSync(dir)) {
        const full = path.join(dir, name);
        const stat = fs.statSync(full);
        if (stat.isDirectory())
            walk(full, out);
        else if (/\.story\.md$/i.test(name))
            out.stories.push(full);
        else if (/^epic\.md$/i.test(name))
            out.epics.push(full);
    }
}
function realCorpusCheck() {
    const root = path.join(process.cwd(), 'docs', 'stories');
    if (!fs.existsSync(root)) {
        console.log('[test_story_parser] docs/stories not present — skipping real-corpus check.');
        return;
    }
    const found = { stories: [], epics: [] };
    walk(root, found);
    assert(found.stories.length >= 1, `expected at least 1 *.story.md under docs/stories/ (found ${found.stories.length})`);
    for (const filePath of found.stories) {
        const content = fs.readFileSync(filePath, 'utf-8');
        const parsed = (0, StoryParser_1.parseStory)(content, filePath);
        assert(parsed.value !== undefined, `parseStory returned no value for ${filePath}`);
        const s = parsed.value;
        assert(/^\d+\.\d+(\.\d+)?$/.test(s.id), `bad id "${s.id}" in ${filePath}`);
        assert(s.epicId.length > 0, `missing epicId in ${filePath}`);
        assert((0, StorySchema_1.isStoryStatus)(s.status), `status "${s.status}" not in ${StorySchema_1.STORY_STATUSES.join(',')} (${filePath})`);
        assert(s.raw === content, 'raw content not preserved');
        if (s.sections['acceptance criteria']) {
            assert(s.acceptanceCriteria.length > 0, `no AC parsed under "## Acceptance Criteria" in ${filePath}`);
        }
    }
    for (const filePath of found.epics) {
        const content = fs.readFileSync(filePath, 'utf-8');
        const parsed = (0, StoryParser_1.parseEpic)(content, filePath);
        assert(parsed.value !== undefined, `parseEpic returned no value for ${filePath}`);
        const e = parsed.value;
        assert(e.id.length > 0, `missing id in epic ${filePath}`);
        assert(e.raw === content, 'raw content not preserved');
    }
    console.log(`[test_story_parser] parsed ${found.stories.length} stories + ${found.epics.length} epics from real corpus.`);
}
function constructedBadInputs() {
    // Missing Status field.
    const bad1 = (0, StoryParser_1.parseStory)('# Story 9.9 — incomplete\n\n**StoryId:** `9.9`\n**Epic:** `epic-x`\n', '/tmp/9.9.story.md');
    assert(bad1.errors.some(e => /Status/i.test(e.message)), 'expected missing-Status error');
    // Unknown status value.
    const bad2 = (0, StoryParser_1.parseStory)('# Story 9.9\n\n**StoryId:** `9.9`\n**Epic:** `epic-x`\n**Status:** Bizarre\n', '/tmp/9.9.story.md');
    assert(bad2.errors.some(e => /unknown Status/i.test(e.message)), 'expected unknown-Status error');
    // Path-derived id when StoryId field is missing.
    const bad3 = (0, StoryParser_1.parseStory)('# Story\n\n**Epic:** `epic-y`\n**Status:** Draft\n', '/tmp/4.2.story.md');
    assert(bad3.value?.id === '4.2', 'expected id to be derived from filename when StoryId missing');
    // AC checkboxes parse both states.
    const ok = (0, StoryParser_1.parseStory)([
        '# Story 9.9',
        '',
        '**StoryId:** `9.9`',
        '**Epic:** `epic-x`',
        '**Status:** Ready',
        '',
        '## Acceptance Criteria',
        '',
        '- [x] one done',
        '- [ ] one open',
    ].join('\n'), '/tmp/9.9.story.md');
    assert(ok.value, 'ok story missing');
    assert(ok.value.acceptanceCriteria.length === 2, 'expected 2 ACs');
    assert(ok.value.acceptanceCriteria[0].checked === true, 'first AC should be checked');
    assert(ok.value.acceptanceCriteria[1].checked === false, 'second AC should be unchecked');
}
function changeLogShape() {
    const content = [
        '# Story 9.9',
        '',
        '**StoryId:** `9.9`',
        '**Epic:** `epic-x`',
        '**Status:** InReview',
        '',
        '## Change Log',
        '',
        '- 2026-05-21 — @dev (Test) — Did the thing.',
        '- 2026-05-22 — po (Pax) — Validated and approved.',
    ].join('\n');
    const parsed = (0, StoryParser_1.parseStory)(content, '/tmp/9.9.story.md');
    assert(parsed.value, 'expected value');
    const cl = parsed.value.changeLog;
    assert(cl.length === 2, `expected 2 changelog entries, got ${cl.length}`);
    assert(cl[0].date === '2026-05-21' && cl[0].author.startsWith('@dev'), `bad first changelog entry: ${JSON.stringify(cl[0])}`);
    assert(cl[1].author.startsWith('po'), `bad second changelog entry: ${JSON.stringify(cl[1])}`);
}
function dependsOnShape() {
    const content = [
        '# Story 3.3',
        '',
        '**StoryId:** `3.3`',
        '**Epic:** `epic-multi-host-installer`',
        '**Status:** Ready',
        '**Depends on:** Story 3.1 (host enum + validator), Story 3.2 (templates)',
    ].join('\n');
    const parsed = (0, StoryParser_1.parseStory)(content, '/tmp/3.3.story.md');
    assert(parsed.value.dependsOn.length === 2, `expected 2 deps, got ${parsed.value.dependsOn}`);
    assert(parsed.value.dependsOn[0] === '3.1' && parsed.value.dependsOn[1] === '3.2', 'deps not parsed to ids');
}
function main() {
    realCorpusCheck();
    constructedBadInputs();
    changeLogShape();
    dependsOnShape();
    console.log('TEST_STORY_PARSER_OK');
}
try {
    main();
}
catch (e) {
    console.error('TEST_STORY_PARSER_FAIL:', e instanceof Error ? e.message : e);
    process.exit(1);
}
