import os
import tempfile
from jinja2 import Template
from loguru import logger
HTML = None
try:
from weasyprint import HTML
except (ImportError, OSError) as e:
logger.warning(f"WeasyPrint failed to load (missing system GTK libraries): {e}. Fallback to HTML-as-PDF simulation is active.")
# A premium, dark-themed HTML template for SRE / Readiness Audit PDF reports
AUDIT_PDF_TEMPLATE = """
Archvise Production Readiness Report
{{ project_name }}
Generated on {{ date_str }}
{{ report.overall_score }}
Production Readiness Score
Critical Panel Findings
{% for agent_id, agent in report.agents.items() %}
{% if agent.findings %}
{% for finding in agent.findings %}
{{ finding.severity }}
{{ finding.issue }}
Location: {{ finding.location }}
Details: {{ finding.engineer_text }}
{% endfor %}
{% endif %}
{% endfor %}
Disclaimer: {{ report.score_disclaimer }}
"""
# A premium, dark-themed HTML template for System Design PDF reports
DESIGN_PDF_TEMPLATE = """
Archvise System Design Blueprint
{{ design.title }}
Generated on {{ date_str }}
Executive Summary (Founder Mode)
{{ design.founder_summary }}
Technical Overview (Engineer Mode)
{{ design.engineer_summary }}
Technology Stack Design
{% for layer, items in design.stack.items() %}
{{ layer }}
{% for item in items %}
{{ item.chip }}
{{ item.reason }}
{% endfor %}
{% endfor %}
Monthly Cost Estimates
| Scale / Tier |
Estimated Cost |
Main Cost Drivers |
| 1,000 active users |
{{ design.cost_estimates['1k_users'].monthly_cost }} |
{{ design.cost_estimates['1k_users'].drivers }} |
| 100,000 active users |
{{ design.cost_estimates['100k_users'].monthly_cost }} |
{{ design.cost_estimates['100k_users'].drivers }} |
| 1,000,000 active users |
{{ design.cost_estimates['1m_users'].monthly_cost }} |
{{ design.cost_estimates['1m_users'].drivers }} |
"""
def generate_audit_pdf(report: dict, project_name: str) -> bytes:
from datetime import datetime
date_str = datetime.utcnow().strftime("%B %d, %Y")
# Render Jinja HTML
template = Template(AUDIT_PDF_TEMPLATE)
html_content = template.render(report=report, project_name=project_name, date_str=date_str)
try:
if HTML is None:
raise RuntimeError("WeasyPrint is not loaded due to missing GTK libraries.")
# Create temp file
with tempfile.NamedTemporaryFile(suffix=".pdf", delete=False) as tmp:
HTML(string=html_content).write_pdf(tmp.name)
tmp.seek(0)
pdf_bytes = tmp.read()
os.unlink(tmp.name)
return pdf_bytes
except Exception as e:
logger.error(f"WeasyPrint PDF generation failed: {e}. Falling back to standard HTML-as-PDF simulation.")
# If WeasyPrint dependencies fail, return simple HTML content in bytes to avoid crashing
return html_content.encode("utf-8")
def generate_design_pdf(design: dict) -> bytes:
from datetime import datetime
date_str = datetime.utcnow().strftime("%B %d, %Y")
# Render Jinja HTML
template = Template(DESIGN_PDF_TEMPLATE)
html_content = template.render(design=design, date_str=date_str)
try:
if HTML is None:
raise RuntimeError("WeasyPrint is not loaded due to missing GTK libraries.")
# Create temp file
with tempfile.NamedTemporaryFile(suffix=".pdf", delete=False) as tmp:
HTML(string=html_content).write_pdf(tmp.name)
tmp.seek(0)
pdf_bytes = tmp.read()
os.unlink(tmp.name)
return pdf_bytes
except Exception as e:
logger.error(f"WeasyPrint PDF generation failed: {e}. Falling back to standard HTML-as-PDF simulation.")
# Return fallback HTML
return html_content.encode("utf-8")