"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createValidationRollupCommand = createValidationRollupCommand;
const node_fs_1 = __importDefault(require("node:fs"));
const errors_1 = require("../../../lib/errors");
const output_1 = require("../../../lib/output");
const cli_constants_1 = require("../../../lib/config/cli-constants");
const doctor_1 = require("../../../lib/doctor");
const paths_1 = require("../../../lib/paths");
const global_format_1 = require("../global-format");
async function createValidationRollupCommand() {
    const { Command } = await import('commander');
    const command = new Command('rollup');
    command
        .description('Run a read-only, local-only validation rollup over supported planning evidence lanes.')
        .option('--scope <scope>', "Validation rollup scope. Currently only 'planning' is supported.", 'planning')
        .option('--format <format>', 'Validation rollup output format. Accepted values: text, json.')
        .option('--artifact <path>', 'Optional repository-relative planning artifact path to focus future rollup evidence.')
        .action((_, commandInstance) => {
        const options = commandInstance.opts();
        const requestedFormat = options.format ?? (0, global_format_1.getGlobalFormat)(commandInstance);
        const format = (0, output_1.resolveOutputFormat)(requestedFormat);
        if (format === null) {
            throw (0, errors_1.createUnsupportedOutputFormatError)({
                received: requestedFormat,
                commandBoundary: 'validation rollup command output format',
            });
        }
        if (options.scope !== 'planning') {
            throw (0, errors_1.createUsageError)("Validation rollup currently supports only the 'planning' scope.", [
                `Received: ${String(options.scope)}`,
            ]);
        }
        const artifactPath = normalizeOptionalArtifactPath(options.artifact);
        assertFocusedArtifactExists(commandInstance, artifactPath);
        const report = (0, doctor_1.runPlanningValidationSmoke)({
            artifactPath: artifactPath ?? undefined,
        });
        const findings = normalizeValidationRollupFindings(report.findings);
        if (findings.some((finding) => finding.severity === 'error')) {
            getRootCommand(commandInstance).runtimeExitCode = errors_1.RuntimeExitCode.ERROR;
        }
        (0, output_1.emitSuccess)({
            command: 'validation rollup',
            format,
            text: renderValidationRollupReport({ ...report, findings }, artifactPath),
            data: {
                repositoryRoot: report.repositoryRoot,
                detectionSource: report.detectionSource,
                scope: 'planning',
                artifact: artifactPath,
                planningRootPath: report.planningRootPath,
                readOnly: true,
                localOnly: true,
                writeCapable: false,
                outputContracts: (0, output_1.getValidationCommandOutputContracts)(),
                readOnlyFailureContract: (0, output_1.getValidationReadOnlyFailureContract)(),
                evidenceSourceInventory: report.evidenceSourceInventory,
                specializedReviewBoundaries: report.specializedReviewBoundaries,
                aggregationContract: report.aggregationContract,
                checks: report.checks,
                inventoryFindings: report.inventoryFindings,
                crossArtifactAlignment: report.crossArtifactAlignment,
                baseline: report.baseline,
                gaps: report.gaps,
                nextActions: report.nextActions,
                nextAction: report.nextAction,
                summary: report.summary,
                readinessStatus: report.readinessStatus,
                implementationState: 'existing',
                noWriteBoundary: cli_constants_1.VALIDATION_ROLLUP_NO_WRITE_BOUNDARY,
            },
            findings,
        });
    });
    return command;
}
function normalizeValidationRollupFindings(findings) {
    return findings.map((finding) => (0, output_1.createValidationFinding)({
        ...finding,
        id: finding.id ?? finding.code,
        code: finding.code ?? finding.id,
        summary: finding.summary ?? finding.message,
        message: finding.message ?? finding.summary,
        detail: finding.detail ?? finding.message ?? finding.summary,
        level: finding.level ?? finding.severity,
        severity: finding.severity ?? finding.level,
        affectedPaths: finding.affectedPaths ??
            (finding.path === undefined
                ? []
                : [
                    (0, output_1.createValidationAffectedPath)({
                        role: 'finding-location',
                        path: finding.path,
                        description: finding.message,
                    }),
                ]),
        artifacts: finding.artifacts ?? [],
        recovery: finding.recovery ?? 'Review the validation rollup evidence before running any write-capable follow-up.',
        evidence: finding.evidence ??
            (0, output_1.createValidationCommandEvidence)({
                category: 'validation-rollup',
                details: {
                    source: 'validation-rollup',
                    noWriteRequired: true,
                },
            }),
    }));
}
function renderValidationRollupReport(report, artifactPath) {
    const suppressedBaselineCount = report.baseline.suppressedFindings + report.baseline.suppressedInventoryFindings + report.baseline.suppressedGaps;
    const lines = [
        (0, output_1.renderTerminalHeading)('Day Shift validation rollup', 'title').trimEnd(),
        '',
        (0, output_1.renderTerminalSection)({
            heading: 'Summary',
            fields: [
                { label: 'Command', value: 'validation rollup' },
                { label: 'Repository root', value: report.repositoryRoot },
                { label: 'Detection source', value: report.detectionSource },
                { label: 'Scope', value: report.scope },
                { label: 'Artifact', value: artifactPath ?? '(none)' },
                { label: 'Mode', value: 'read-only, local-only' },
                { label: 'Write capable', value: 'no' },
                { label: 'Planning root', value: report.planningRootPath },
                { label: 'Readiness status', value: report.readinessStatus },
                {
                    label: 'Checks',
                    value: `${report.summary.totalChecks} total, ${report.summary.passed} passed, ${report.summary.informational} informational, ${report.summary.warnings} warnings, ${report.summary.errors} errors`,
                },
                { label: 'Source lanes', value: report.aggregationContract.sourceLaneFields.join(', ') },
                { label: 'Findings', value: report.findings.length },
                { label: 'Inventory findings', value: report.inventoryFindings.length },
                { label: 'Planning gaps', value: report.gaps.length },
                {
                    label: 'Forward-only baseline',
                    value: report.baseline.present ? `${report.baseline.path} (${suppressedBaselineCount} suppressed)` : 'none',
                },
                {
                    label: 'Baseline read evidence only',
                    value: report.baseline.present ? 'existing checkpoint was read' : 'no checkpoint was read',
                },
                { label: 'No-write boundary', value: cli_constants_1.VALIDATION_ROLLUP_NO_WRITE_BOUNDARY },
            ],
            lines: [(0, output_1.renderTerminalBoundary)({ kind: 'read-only' })],
        }),
        '',
        (0, output_1.renderTerminalCompactList)({
            heading: 'Check results:',
            entries: report.checks.map((check) => ({
                label: `[${check.status}] ${check.id}`,
                lines: [check.message],
            })),
        }),
    ];
    lines.push('', (0, output_1.renderValidationFindingsText)(report.findings, 'Structured findings'));
    lines.push('', 'Inventory findings:');
    if (report.inventoryFindings.length === 0) {
        lines.push('- (none)');
    }
    else {
        for (const finding of report.inventoryFindings) {
            lines.push(`- ${finding}`);
        }
    }
    lines.push('', 'Planning gaps:');
    if (report.gaps.length === 0) {
        lines.push('- (none)');
    }
    else {
        for (const gap of report.gaps) {
            lines.push(`- [${gap.code}] ${gap.message}`);
        }
    }
    lines.push('', 'Cross-artifact alignment:');
    lines.push(`- selected family: ${report.crossArtifactAlignment.selectedArtifactFamily}`, `- surface mode: ${report.crossArtifactAlignment.surfaceMode}`, `- no-write: ${report.crossArtifactAlignment.noWrite ? 'yes' : 'no'}`, `- findings taxonomy: ${report.crossArtifactAlignment.findingsTaxonomy}`);
    for (const lane of report.crossArtifactAlignment.lanes) {
        lines.push(`- [${lane.status}] ${lane.id}: ${lane.findings.length} finding${lane.findings.length === 1 ? '' : 's'}`);
    }
    lines.push('', 'Evidence-source inventory:');
    for (const source of report.evidenceSourceInventory) {
        lines.push(`- ${source.id}: ${source.evidenceShapes.join(', ')} (${source.producer.command ?? source.producer.functionName ?? source.producer.path})`);
    }
    lines.push('', 'Specialized review boundaries:');
    for (const boundary of report.specializedReviewBoundaries) {
        lines.push(`- ${boundary.id}: ${boundary.command} (${boundary.rollupExecution})`);
    }
    lines.push('', 'Aggregation contract:');
    for (const lane of report.aggregationContract.lanes) {
        lines.push(`- ${lane.id}: ${String(lane.reportField)} from ${lane.sourceEvidence}`);
    }
    lines.push(`- baseline policy: ${report.aggregationContract.baselinePolicy}`, `- next-action policy: ${report.aggregationContract.nextActionPolicy}`, `- aggregation no-write boundary: ${report.aggregationContract.noWriteBoundary}`);
    lines.push('', 'Next actions:');
    if (report.nextActions.length === 0) {
        lines.push('- (none)');
    }
    else {
        for (const action of report.nextActions) {
            lines.push(`- ${action}`);
        }
    }
    if (report.nextAction !== null) {
        lines.push('', 'Artifact guidance:', `- ${report.nextAction.command ?? report.nextAction.recommendation}`);
    }
    return lines.join('\n');
}
function normalizeOptionalArtifactPath(input) {
    if (input === undefined || input === null || input === '') {
        return null;
    }
    if (typeof input !== 'string') {
        throw (0, errors_1.createUsageError)('Validation rollup artifact path must be a repository-relative path.', [
            `Received: ${String(input)}`,
        ]);
    }
    try {
        return (0, paths_1.parseRepositoryRelativePath)(input).normalizedPath;
    }
    catch (error) {
        if (error instanceof RangeError) {
            throw (0, errors_1.createUsageError)('Validation rollup artifact path must be a repository-relative path.', [error.message]);
        }
        throw error;
    }
}
function assertFocusedArtifactExists(commandInstance, artifactPath) {
    if (artifactPath === null) {
        return;
    }
    const repositoryRoot = getRootCommand(commandInstance).configRepositoryContext?.root;
    if (typeof repositoryRoot !== 'string' || repositoryRoot.trim() === '') {
        return;
    }
    const absolutePath = (0, paths_1.resolveRepositoryRelativePath)(repositoryRoot, artifactPath);
    if (node_fs_1.default.existsSync(absolutePath)) {
        return;
    }
    throw new errors_1.RuntimeError({
        message: 'Validation rollup artifact evidence is missing.',
        code: 'VALIDATION_ROLLUP_ARTIFACT_MISSING',
        exitCode: errors_1.RuntimeExitCode.ERROR,
        details: [`No local artifact exists at: ${artifactPath}`],
        findings: [
            {
                id: 'VALIDATION_ROLLUP_ARTIFACT_MISSING',
                code: 'VALIDATION_ROLLUP_ARTIFACT_MISSING',
                summary: 'Validation rollup artifact evidence is missing.',
                message: 'Validation rollup artifact evidence is missing.',
                level: 'error',
                severity: 'error',
                path: artifactPath,
                recovery: 'Provide an existing repository-relative planning artifact path or rerun without --artifact for repo-wide rollup evidence.',
                evidence: {
                    category: 'validation-rollup',
                    details: {
                        blockingReason: 'invalid-command-input',
                        noWriteRequired: true,
                    },
                },
            },
        ],
    });
}
function getRootCommand(commandInstance) {
    let current = commandInstance;
    while (current?.parent != null) {
        current = current.parent;
    }
    return (current ?? commandInstance);
}
