/**
 * Proof Report Generator — Multi-format evidence reports
 *
 * Generates reports in three formats:
 * - HTML: Self-contained with embedded base64 images, dark theme
 * - Markdown: Lightweight summary for PR descriptions and ticket comments
 * - Archive: HTML with embedded proof.json manifest for full portability
 *
 * No external dependencies — works offline.
 */
function escapeHtml(str) {
    return str
        .replace(/&/g, '&amp;')
        .replace(/</g, '&lt;')
        .replace(/>/g, '&gt;')
        .replace(/"/g, '&quot;');
}
function statusBadge(status) {
    const colors = {
        pass: '#22c55e',
        approved: '#22c55e',
        fail: '#ef4444',
        rejected: '#ef4444',
        partial: '#f59e0b',
        'approved-with-notes': '#f59e0b',
        skip: '#6b7280',
        error: '#ef4444',
    };
    const color = colors[status] ?? '#6b7280';
    return `<span style="background:${color};color:#fff;padding:2px 10px;border-radius:12px;font-size:13px;font-weight:600;text-transform:uppercase;">${escapeHtml(status)}</span>`;
}
function renderDimensionBar(score, label, rationale) {
    const pct = score * 10;
    const color = score >= 7 ? '#22c55e' : score >= 5 ? '#f59e0b' : '#ef4444';
    return `
		<div style="margin-bottom:12px;">
			<div style="display:flex;justify-content:space-between;margin-bottom:4px;">
				<span style="font-weight:600;text-transform:capitalize;">${escapeHtml(label)}</span>
				<span style="font-weight:700;color:${color};">${score}/10</span>
			</div>
			<div style="background:#1e293b;border-radius:6px;height:8px;overflow:hidden;">
				<div style="background:${color};height:100%;width:${pct}%;border-radius:6px;transition:width 0.6s;"></div>
			</div>
			<div style="font-size:12px;color:#94a3b8;margin-top:2px;">${escapeHtml(rationale)}</div>
		</div>`;
}
function renderCheck(label, status, detail) {
    const icon = status === 'pass' ? '&#10004;' : '&#10008;';
    const color = status === 'pass' ? '#22c55e' : '#ef4444';
    return `
		<div style="display:flex;align-items:center;gap:8px;padding:8px 0;border-bottom:1px solid #1e293b;">
			<span style="color:${color};font-size:18px;">${icon}</span>
			<span style="font-weight:600;">${escapeHtml(label)}</span>
			<span style="color:#94a3b8;font-size:13px;margin-left:auto;">${escapeHtml(detail)}</span>
		</div>`;
}
function renderTerminal(output, label) {
    return `
		<details style="margin-top:8px;">
			<summary style="cursor:pointer;color:#60a5fa;font-size:13px;">Terminal: ${escapeHtml(label)}</summary>
			<pre style="background:#0f172a;border:1px solid #1e293b;border-radius:8px;padding:12px;margin-top:6px;overflow-x:auto;font-size:12px;line-height:1.5;color:#e2e8f0;max-height:400px;overflow-y:auto;">${escapeHtml(output)}</pre>
		</details>`;
}
function renderScreenshot(entry) {
    if (!entry.imageData)
        return '';
    return `
		<div style="margin-top:8px;">
			<div style="font-size:12px;color:#94a3b8;margin-bottom:4px;">Screenshot: ${escapeHtml(entry.label)}</div>
			<img src="data:image/png;base64,${entry.imageData}" style="max-width:100%;border-radius:8px;border:1px solid #1e293b;" alt="${escapeHtml(entry.label)}" />
		</div>`;
}
function renderEntry(entry) {
    const parts = [];
    parts.push(`
		<div style="padding:8px 12px;border-left:3px solid ${entry.result === 'pass' ? '#22c55e' : entry.result === 'fail' ? '#ef4444' : '#6b7280'};margin-bottom:8px;background:#0f172a;border-radius:0 6px 6px 0;">
			<div style="display:flex;align-items:center;gap:8px;">
				${statusBadge(entry.result)}
				<span style="font-size:13px;">${entry.step ? `Step ${entry.step}: ` : ''}${escapeHtml(entry.description)}</span>
				${entry.duration ? `<span style="color:#64748b;font-size:11px;margin-left:auto;">${entry.duration}ms</span>` : ''}
			</div>`);
    if (entry.type === 'screenshot') {
        parts.push(renderScreenshot(entry));
    }
    if (entry.type === 'terminal' && entry.terminalOutput) {
        parts.push(renderTerminal(entry.terminalOutput, entry.label));
    }
    if (entry.type === 'assertion' && entry.assertion) {
        parts.push(`
			<div style="font-size:12px;color:#94a3b8;margin-top:4px;">
				<code>${escapeHtml(entry.assertion.expression)}</code>
				&mdash; expected: <code>${escapeHtml(entry.assertion.expected)}</code>,
				actual: <code>${escapeHtml(entry.assertion.actual)}</code>
			</div>`);
    }
    parts.push('</div>');
    return parts.join('');
}
function renderFeature(feature) {
    const entryHtml = feature.entries.map(renderEntry).join('');
    const passCount = feature.entries.filter((e) => e.result === 'pass').length;
    const total = feature.entries.length;
    return `
		<div style="background:#1a1a2e;border:1px solid #1e293b;border-radius:12px;padding:20px;margin-bottom:16px;">
			<div style="display:flex;align-items:center;gap:12px;margin-bottom:12px;">
				${statusBadge(feature.result)}
				<h3 style="margin:0;font-size:16px;">${escapeHtml(feature.name)}</h3>
				<span style="color:#64748b;font-size:13px;margin-left:auto;">${passCount}/${total} steps</span>
			</div>
			${feature.route ? `<div style="font-size:12px;color:#64748b;margin-bottom:8px;">Route: ${escapeHtml(feature.route)}</div>` : ''}
			${feature.mcpServer ? `<div style="font-size:12px;color:#64748b;margin-bottom:8px;">MCP: ${escapeHtml(feature.mcpServer)}</div>` : ''}
			${entryHtml}
		</div>`;
}
function renderVerdict(verdict) {
    const providerColors = {
        claude: '#d97706',
        gemini: '#4285f4',
        codex: '#10b981',
    };
    const color = providerColors[verdict.provider] ?? '#6b7280';
    return `
		<div style="background:#1a1a2e;border:1px solid #1e293b;border-radius:12px;padding:20px;margin-bottom:12px;">
			<div style="display:flex;align-items:center;gap:12px;margin-bottom:8px;">
				<span style="background:${color};color:#fff;padding:2px 10px;border-radius:12px;font-size:12px;font-weight:600;">${escapeHtml(verdict.provider)}</span>
				${statusBadge(verdict.verdict)}
				<span style="font-size:13px;color:#94a3b8;">${escapeHtml(verdict.model)}</span>
				<span style="color:#64748b;font-size:12px;margin-left:auto;">confidence: ${Math.round(verdict.confidence * 100)}%</span>
			</div>
			<div style="font-size:13px;color:#94a3b8;margin-bottom:4px;font-weight:600;">Role: ${escapeHtml(verdict.role)}</div>
			<p style="font-size:14px;margin:8px 0;">${escapeHtml(verdict.summary)}</p>
			${verdict.findings.length > 0
        ? `<ul style="margin:4px 0 0 0;padding-left:20px;font-size:13px;color:#cbd5e1;">${verdict.findings.map((f) => `<li>${escapeHtml(f)}</li>`).join('')}</ul>`
        : ''}
		</div>`;
}
/** Generate a self-contained HTML proof report */
export function generateProofHtml(manifest, title) {
    const reportTitle = title ?? `Proof Report — ${manifest.appName}`;
    const totalFeatures = manifest.features.length;
    const passedFeatures = manifest.features.filter((f) => f.result === 'pass').length;
    const qaStatus = manifest.qaSignoff.status;
    const dimensions = manifest.qaSignoff.dimensions;
    const checksHtml = [
        renderCheck('Tests', manifest.checks.tests.status, `${manifest.checks.tests.count} tests`),
        renderCheck('Type Check', manifest.checks.typecheck.status, manifest.checks.typecheck.errors.length > 0
            ? `${manifest.checks.typecheck.errors.length} errors`
            : 'clean'),
        renderCheck('Lint', manifest.checks.lint.status, manifest.checks.lint.warnings > 0 ? `${manifest.checks.lint.warnings} warnings` : 'clean'),
    ].join('');
    const dimensionsHtml = dimensions
        .map((d) => renderDimensionBar(d.score, d.dimension, d.rationale))
        .join('');
    const featuresHtml = manifest.features.map(renderFeature).join('');
    const verdictsHtml = manifest.verdicts.length > 0 ? manifest.verdicts.map(renderVerdict).join('') : '';
    const quorumHtml = manifest.quorum
        ? `
		<div style="background:#1a1a2e;border:2px solid ${manifest.quorum.finalVerdict === 'pass' ? '#22c55e' : manifest.quorum.finalVerdict === 'fail' ? '#ef4444' : '#f59e0b'};border-radius:12px;padding:20px;margin-bottom:24px;text-align:center;">
			<div style="font-size:14px;color:#94a3b8;margin-bottom:8px;">VERIFICATION QUORUM</div>
			<div style="font-size:28px;font-weight:700;margin-bottom:8px;">${statusBadge(manifest.quorum.finalVerdict)}</div>
			<div style="font-size:13px;color:#64748b;">
				${manifest.quorum.modelsUsed.map(escapeHtml).join(' + ')}
				&mdash; ${manifest.quorum.unanimous ? 'Unanimous' : 'Majority'}
			</div>
		</div>`
        : '';
    const terminalOutputs = [
        manifest.checks.tests.output ? renderTerminal(manifest.checks.tests.output, 'Test Suite') : '',
        manifest.checks.typecheck.output
            ? renderTerminal(manifest.checks.typecheck.output, 'Type Check')
            : '',
        manifest.checks.lint.output ? renderTerminal(manifest.checks.lint.output, 'Lint') : '',
    ].join('');
    return `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>${escapeHtml(reportTitle)}</title>
<style>
	* { box-sizing: border-box; margin: 0; padding: 0; }
	body {
		font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
		background: #0a0a1a;
		color: #e2e8f0;
		padding: 24px;
		line-height: 1.6;
	}
	.container { max-width: 900px; margin: 0 auto; }
	h1 { font-size: 24px; margin-bottom: 4px; }
	h2 { font-size: 18px; margin-bottom: 12px; color: #f1f5f9; }
	.meta { color: #64748b; font-size: 13px; margin-bottom: 24px; }
	.section { margin-bottom: 32px; }
	.card {
		background: #1a1a2e;
		border: 1px solid #1e293b;
		border-radius: 12px;
		padding: 20px;
		margin-bottom: 16px;
	}
	.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
	@media (max-width: 640px) { .grid-2 { grid-template-columns: 1fr; } }
	.hero {
		text-align: center;
		padding: 32px 0;
		border-bottom: 1px solid #1e293b;
		margin-bottom: 32px;
	}
	.hero-status { font-size: 40px; margin: 16px 0; }
	.stat { text-align: center; padding: 16px; }
	.stat-value { font-size: 28px; font-weight: 700; }
	.stat-label { font-size: 12px; color: #64748b; text-transform: uppercase; }
	details summary { user-select: none; }
	details summary:hover { color: #93c5fd; }
	.footer { text-align: center; color: #475569; font-size: 12px; padding: 24px 0; border-top: 1px solid #1e293b; margin-top: 32px; }
</style>
</head>
<body>
<div class="container">

<div class="hero">
	<h1>${escapeHtml(reportTitle)}</h1>
	<div class="meta">
		Run: ${escapeHtml(manifest.runId)} &bull;
		${escapeHtml(manifest.startedAt)} &rarr; ${escapeHtml(manifest.completedAt)}
	</div>
	<div class="hero-status">${statusBadge(qaStatus)}</div>
	<div style="margin-top:12px;">
		<div class="grid-2" style="max-width:400px;margin:0 auto;">
			<div class="stat">
				<div class="stat-value">${passedFeatures}/${totalFeatures}</div>
				<div class="stat-label">Features Verified</div>
			</div>
			<div class="stat">
				<div class="stat-value">${manifest.qaSignoff.iterations}</div>
				<div class="stat-label">Iterations</div>
			</div>
		</div>
	</div>
</div>

${quorumHtml}

<div class="section">
	<h2>QA Dimensions</h2>
	<div class="card">
		${dimensionsHtml}
	</div>
</div>

<div class="section">
	<h2>Automated Checks</h2>
	<div class="card">
		${checksHtml}
	</div>
	${terminalOutputs}
</div>

${manifest.verdicts.length > 0
        ? `
<div class="section">
	<h2>Multi-Model Verdicts</h2>
	${verdictsHtml}
</div>`
        : ''}

<div class="section">
	<h2>Feature Evidence</h2>
	${featuresHtml || '<div class="card" style="color:#64748b;">No feature-level evidence captured. Use testable_features.json to define features for visual verification.</div>'}
</div>

${manifest.qaSignoff.issues.length > 0
        ? `
<div class="section">
	<h2>Issues</h2>
	<div class="card">
		${manifest.qaSignoff.issues
            .map((issue) => `
		<div style="padding:8px 0;border-bottom:1px solid #1e293b;">
			<span style="background:${issue.severity === 'critical' ? '#ef4444' : issue.severity === 'warning' ? '#f59e0b' : '#6b7280'};color:#fff;padding:1px 8px;border-radius:8px;font-size:11px;font-weight:600;">${escapeHtml(issue.severity)}</span>
			<span style="margin-left:8px;font-size:13px;">${escapeHtml(issue.file)}</span>
			<div style="font-size:13px;color:#94a3b8;margin-top:2px;">${escapeHtml(issue.description)}</div>
		</div>`)
            .join('')}
	</div>
</div>`
        : ''}

<div class="footer">
	Generated by Aperant Framework &bull; Self-contained proof report &bull; No external dependencies
</div>

</div>
</body>
</html>`;
}
/** Generate a markdown proof report — lightweight, suitable for PR descriptions */
export function generateProofMarkdown(manifest, title) {
    const reportTitle = title ?? `Proof Report: ${manifest.appName}`;
    const dims = manifest.qaSignoff.dimensions;
    const date = manifest.startedAt.split('T')[0];
    const lines = [];
    lines.push(`# ${reportTitle}`);
    lines.push('');
    lines.push(`**Status:** ${manifest.qaSignoff.status.toUpperCase()} | **Run:** ${manifest.runId} | **Date:** ${date}`);
    lines.push('');
    // QA Scores
    lines.push('## QA Scores');
    lines.push('| Dimension | Score | Rationale |');
    lines.push('|-----------|-------|-----------|');
    for (const d of dims) {
        lines.push(`| ${d.dimension} | ${d.score}/10 | ${d.rationale} |`);
    }
    lines.push('');
    // Checks
    lines.push('## Checks');
    lines.push(`- Tests: ${manifest.checks.tests.status} (${manifest.checks.tests.count} tests)`);
    lines.push(`- Types: ${manifest.checks.typecheck.status}${manifest.checks.typecheck.errors.length > 0 ? ` (${manifest.checks.typecheck.errors.length} errors)` : ''}`);
    lines.push(`- Lint: ${manifest.checks.lint.status}${manifest.checks.lint.warnings > 0 ? ` (${manifest.checks.lint.warnings} warnings)` : ''}`);
    lines.push('');
    // Features
    if (manifest.features.length > 0) {
        lines.push('## Features Verified');
        for (const f of manifest.features) {
            const passCount = f.entries.filter((e) => e.result === 'pass').length;
            lines.push(`- **${f.name}**: ${f.result} (${passCount}/${f.entries.length} steps)`);
        }
        lines.push('');
    }
    // Quorum
    if (manifest.quorum && manifest.verdicts.length > 0) {
        lines.push('## Verification Quorum');
        lines.push('| Model | Provider | Verdict | Confidence |');
        lines.push('|-------|----------|---------|------------|');
        for (const v of manifest.verdicts) {
            lines.push(`| ${v.model} | ${v.provider} | ${v.verdict} | ${Math.round(v.confidence * 100)}% |`);
        }
        lines.push('');
        lines.push(`**Quorum result:** ${manifest.quorum.unanimous ? 'Unanimous' : 'Majority'} ${manifest.quorum.finalVerdict}`);
        lines.push('');
    }
    // Issues
    if (manifest.qaSignoff.issues.length > 0) {
        lines.push('## Issues');
        for (const issue of manifest.qaSignoff.issues) {
            lines.push(`- **[${issue.severity}]** \`${issue.file}\`: ${issue.description}`);
        }
        lines.push('');
    }
    lines.push('---');
    lines.push('*Generated by Aperant Framework*');
    return lines.join('\n');
}
/** Generate an archive HTML — self-contained HTML with embedded proof.json manifest */
export function generateProofArchive(manifest, title) {
    const html = generateProofHtml(manifest, title);
    const manifestJson = JSON.stringify(manifest, null, 2);
    // Inject the manifest as a machine-readable block before closing </body>
    return html.replace('</body>', `<script type="application/json" id="proof-manifest">\n${manifestJson}\n</script>\n</body>`);
}
//# sourceMappingURL=proof-report.js.map