from __future__ import annotations
import os
from typing import Any, Dict, List
from reportlab.lib.pagesizes import LETTER
from reportlab.pdfgen import canvas
def render_markdown(snapshot: Dict[str, Any], findings: List[Dict[str, Any]], cost: Dict[str, Any], cost_explorer: Dict[str, Any]) -> str:
meta = snapshot.get("meta", {})
lines: List[str] = []
lines.append(f"# AWS Audit Snapshot — {meta.get('account_id', 'unknown')}")
lines.append("")
lines.append(f"- Snapshot ID: `{meta.get('snapshot_id')}`")
lines.append(f"- Collected: `{meta.get('collected_at')}`")
lines.append(f"- Regions: {', '.join(meta.get('regions', []))}")
lines.append("")
lines.append("## Executive Summary")
lines.append(f"- Findings: **{len(findings)}**")
lines.append("")
lines.append("## Top Findings")
if not findings:
lines.append("- No findings generated.")
else:
# show first 15
for f in findings[:15]:
lines.append(f"- **{f.get('severity')}** — {f.get('title')} ({f.get('region') or 'global'})")
lines.append("")
lines.append("## Cost Snapshot")
if cost:
lines.append("### Tier 1 (inventory-derived signals)")
lines.append(f"- Unattached EBS (GB): {cost.get('unattached_ebs_gb')}")
lines.append(f"- Unassociated EIPs: {cost.get('unassociated_eips')}")
lines.append("")
if cost_explorer and cost_explorer.get("results"):
lines.append("### Tier 2 (Cost Explorer)")
lines.append(f"- Range: {cost_explorer.get('time_period')}")
lines.append(f"- Points: {len(cost_explorer.get('results', []))}")
lines.append("")
elif cost_explorer and cost_explorer.get("error"):
lines.append("### Tier 2 (Cost Explorer)")
lines.append(f"- Not available: {cost_explorer.get('error')}")
lines.append("")
lines.append("## Inventory Summary")
summary = snapshot.get("summary", {})
for k, v in summary.items():
lines.append(f"- {k}: {v}")
lines.append("")
return "\n".join(lines)
def write_pdf_from_text(pdf_path: str, title: str, text: str) -> None:
os.makedirs(os.path.dirname(pdf_path), exist_ok=True)
c = canvas.Canvas(pdf_path, pagesize=LETTER)
width, height = LETTER
y = height - 72
c.setTitle(title)
for raw in text.splitlines():
if y < 72:
c.showPage()
y = height - 72
c.drawString(72, y, raw[:1200])
y -= 14
c.save()