/** * UAIDE — Forensic Report Generator * Produces a self-contained, print-ready HTML report blob for download. */ const VERDICT_LABEL = { authentic: 'AUTHENTIC', ai_generated: 'AI-GENERATED', suspect: 'SUSPECT / INCONCLUSIVE', }; const VERDICT_COLOR = { authentic: '#00c67a', ai_generated: '#ff4757', suspect: '#f59e0b', }; const SEV_COLOR = { critical: '#ff4757', high: '#f59e0b', medium: '#7c3aed', low: '#8896ab', }; function escapeHtml(str) { return String(str ?? '—') .replace(/&/g, '&') .replace(//g, '>') .replace(/"/g, '"'); } function modelBreakdownRows(models) { return models.map(m => ` ${escapeHtml(m.model)} ${m.score.toFixed(1)}%
${(m.weight * 100).toFixed(0)}% `).join(''); } function artifactRows(artifacts) { return artifacts.map(a => ` ${a.severity.toUpperCase()} ${escapeHtml(a.type)} ${escapeHtml(a.detail)} `).join(''); } function timelineSection(result) { if (result.type !== 'video' || !result.timeline) return ''; const segments = result.timeline.flaggedSegments.map(s => ` ${s.severity.toUpperCase()} ${escapeHtml(s.reason)} ${s.start.toFixed(1)}s – ${s.end.toFixed(1)}s ${s.frames.length} frames `).join(''); return `

4. Temporal Analysis

Total flagged segments: ${result.timeline.flaggedSegments.length}  |  Clean segments: ${result.timeline.cleanSegments.length}

${segments}
SeverityAnomalyTimestampFrames
`; } function metadataRows(meta) { return Object.entries(meta).map(([key, val]) => { const label = key.replace(/([A-Z])/g, ' $1').replace(/^./, s => s.toUpperCase()); return `${escapeHtml(label)}${escapeHtml(val)}`; }).join(''); } function gradcamTable(regions) { return regions.map(r => ` ${escapeHtml(r.label)} ${Math.round(r.intensity * 100)}% ${r.intensity > 0.8 ? 'High' : r.intensity > 0.5 ? 'Medium' : 'Low'} x:${r.x}% y:${r.y}% w:${r.w}% h:${r.h}% `).join(''); } export function generateReport(result, previewUrl) { const verdictColor = VERDICT_COLOR[result.verdict]; const verdictLabel = VERDICT_LABEL[result.verdict]; const now = new Date().toUTCString(); const html = ` UAIDE Forensic Report — ${escapeHtml(result.filename)}

Forensic Analysis Report

${escapeHtml(result.filename)}  ·  Analysis ID: ${escapeHtml(result.analysisId)}

${verdictLabel}  — ${result.confidenceScore.toFixed(1)}% confidence
File ${escapeHtml(result.filename)}
Type ${escapeHtml(result.format)}
Resolution ${escapeHtml(result.resolution)}
File Size ${escapeHtml(result.filesize)}
Processing Time ${escapeHtml(result.processingTime)}
Report Generated ${now}

1. Executive Summary

${result.confidenceScore.toFixed(1)}%
AI Involvement Confidence Score

Verdict: ${verdictLabel}

${result.verdict === 'authentic' ? 'Multi-model ensemble analysis found no significant generative artifacts. Content is consistent with authentic human-captured media.' : result.verdict === 'ai_generated' ? 'Multi-model ensemble analysis detected strong generative artifacts consistent with GAN or diffusion model synthesis. Content is highly likely to be AI-generated.' : 'Multi-model ensemble analysis produced inconclusive results. The media exhibits some characteristics of synthetic generation but does not conclusively meet the threshold for either verdict. Manual expert review is advised.'}

Models Run
${result.modelBreakdown.length}
Artifacts Found
${result.artifacts.length}
Spectral Anomaly
${result.fft.spectralAnomaly ? 'Detected' : 'Not Found'}

2. Media Under Analysis

${result.type === 'image' ? `Analysed media — ${escapeHtml(result.filename)}` : `

Video preview not embedded in static report
File: ${escapeHtml(result.filename)} · ${escapeHtml(result.duration)} · ${result.totalFrames} frames

` }

${escapeHtml(result.filename)}  ·  ${escapeHtml(result.resolution)}  ·  ${escapeHtml(result.filesize)}

3. Model Ensemble Results

The following forensic deep learning models were run in ensemble. Each model independently scores the likelihood of AI generation; results are weighted and fused into the final confidence score.

${modelBreakdownRows(result.modelBreakdown)}
Model Score Confidence Bar Weight
${timelineSection(result)}

${result.type === 'video' ? '5' : '4'}. Grad-CAM Artifact Localisation

Gradient-weighted Class Activation Mapping (Grad-CAM) was applied to highlight spatial regions in the media that contributed most to the AI-generation classification decision.

${gradcamTable(result.gradcam.regions)}
RegionIntensityLevelBounding Box

${result.type === 'video' ? '6' : '5'}. Detected Artifacts & Generative Fingerprints

${artifactRows(result.artifacts)}
SeverityTypeDetail

${result.type === 'video' ? '7' : '6'}. Frequency Domain Analysis (FFT)

${result.fft.spectralAnomaly ? `
⚠ Spectral anomaly detected in the frequency domain — a strong indicator of generative upsampling or GAN synthesis.
` : ''}
Peak Frequency
${escapeHtml(result.fft.peakFrequency)}
Anomaly Bands
${escapeHtml(result.fft.anomalyBands.join(', '))}
DCT Coefficients
${escapeHtml(result.fft.dctCoefficients)}
Noise Pattern
${escapeHtml(result.fft.noisePattern)}

${result.type === 'video' ? '8' : '7'}. File Metadata

${metadataRows(result.metadata)}
FieldValue
Disclaimer: This report was generated automatically by UAIDE (Unified AI Origin Detection Engine) v2.4 — Research Preview. All results are probabilistic in nature and based on ensemble deep learning inference. No automated system can guarantee 100% accuracy in AI-generated content detection. These findings must be corroborated with expert human review before being used as evidence in any legal, academic, or journalistic context. UAIDE is developed for academic research and investigative purposes.

Report generated: ${now}  ·  Analysis ID: ${escapeHtml(result.analysisId)}  ·  github.com/Deshna24/UAIDE
`; return html; } export function downloadReport(result, previewUrl) { const html = generateReport(result, previewUrl); const blob = new Blob([html], { type: 'text/html;charset=utf-8' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; const safeName = result.filename.replace(/\.[^.]+$/, '').replace(/[^a-zA-Z0-9_-]/g, '_'); a.download = `UAIDE_Report_${safeName}_${result.analysisId}.html`; document.body.appendChild(a); a.click(); document.body.removeChild(a); setTimeout(() => URL.revokeObjectURL(url), 10000); }