""" PDF Report Generator for Farmer.Chat Exports query results as downloadable PDF """ from reportlab.lib.pagesizes import letter, A4 from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle from reportlab.lib.units import inch from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle, PageBreak from reportlab.lib import colors from reportlab.lib.enums import TA_CENTER, TA_LEFT from datetime import datetime import json import os from typing import Dict, Any def generate_pdf_report( query: str, advice: str, data: Dict[str, Any], location: Dict[str, Any] ) -> str: """ Generate PDF report from query results Args: query: Farmer's question advice: Generated advice data: Compiled data from MCP servers location: Location information Returns: str: Path to generated PDF file """ # Create output directory output_dir = "./pdf_reports" os.makedirs(output_dir, exist_ok=True) # Generate filename timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") filename = f"farmer_chat_report_{timestamp}.pdf" filepath = os.path.join(output_dir, filename) # Create PDF doc = SimpleDocTemplate(filepath, pagesize=letter) story = [] styles = getSampleStyleSheet() # Custom styles title_style = ParagraphStyle( 'CustomTitle', parent=styles['Heading1'], fontSize=24, textColor=colors.HexColor('#2E7D32'), spaceAfter=30, alignment=TA_CENTER ) heading_style = ParagraphStyle( 'CustomHeading', parent=styles['Heading2'], fontSize=16, textColor=colors.HexColor('#1B5E20'), spaceAfter=12, spaceBefore=20 ) # Title story.append(Paragraph("🌾 Farmer.Chat Report", title_style)) story.append(Spacer(1, 0.2*inch)) # Metadata section metadata_data = [ ["Report Generated:", datetime.now().strftime("%B %d, %Y at %I:%M %p")], ["Location:", f"{location['name']}"], ["Coordinates:", f"{location['lat']}°N, {location['lon']}°E"], ["Data Sources:", f"{len(data.get('successful_servers', []))} MCP Servers"] ] metadata_table = Table(metadata_data, colWidths=[2*inch, 4*inch]) metadata_table.setStyle(TableStyle([ ('BACKGROUND', (0, 0), (0, -1), colors.HexColor('#E8F5E9')), ('TEXTCOLOR', (0, 0), (-1, -1), colors.black), ('ALIGN', (0, 0), (-1, -1), 'LEFT'), ('FONTNAME', (0, 0), (0, -1), 'Helvetica-Bold'), ('FONTNAME', (1, 0), (1, -1), 'Helvetica'), ('FONTSIZE', (0, 0), (-1, -1), 10), ('BOTTOMPADDING', (0, 0), (-1, -1), 8), ('GRID', (0, 0), (-1, -1), 1, colors.grey) ])) story.append(metadata_table) story.append(Spacer(1, 0.3*inch)) # Query section story.append(Paragraph("Your Query", heading_style)) story.append(Paragraph(query, styles['Normal'])) story.append(Spacer(1, 0.2*inch)) # Advice section story.append(Paragraph("Recommendations", heading_style)) # Split advice into paragraphs advice_paragraphs = advice.split('\n\n') for para in advice_paragraphs: if para.strip(): story.append(Paragraph(para.strip(), styles['Normal'])) story.append(Spacer(1, 0.1*inch)) story.append(Spacer(1, 0.2*inch)) # Data section story.append(Paragraph("Data Sources", heading_style)) compiled_data = data.get('data', {}) for server_name, server_data in compiled_data.items(): # Server heading server_title = server_name.replace('_', ' ').title() story.append(Paragraph(f"{server_title}", styles['Normal'])) story.append(Spacer(1, 0.05*inch)) # Server data table server_items = [] if isinstance(server_data, dict): for key, value in server_data.items(): if isinstance(value, (str, int, float)): display_key = key.replace('_', ' ').title() server_items.append([display_key, str(value)]) if server_items: data_table = Table(server_items, colWidths=[2.5*inch, 3.5*inch]) data_table.setStyle(TableStyle([ ('BACKGROUND', (0, 0), (0, -1), colors.HexColor('#F1F8E9')), ('TEXTCOLOR', (0, 0), (-1, -1), colors.black), ('ALIGN', (0, 0), (-1, -1), 'LEFT'), ('FONTNAME', (0, 0), (0, -1), 'Helvetica'), ('FONTNAME', (1, 0), (1, -1), 'Helvetica'), ('FONTSIZE', (0, 0), (-1, -1), 9), ('BOTTOMPADDING', (0, 0), (-1, -1), 6), ('GRID', (0, 0), (-1, -1), 0.5, colors.grey) ])) story.append(data_table) story.append(Spacer(1, 0.15*inch)) # Footer story.append(Spacer(1, 0.3*inch)) footer_style = ParagraphStyle( 'Footer', parent=styles['Normal'], fontSize=9, textColor=colors.grey, alignment=TA_CENTER ) story.append(Paragraph("Generated by Farmer.Chat - Agricultural Intelligence System", footer_style)) story.append(Paragraph("Powered by Multi-stage MCP Pipeline", footer_style)) # Build PDF doc.build(story) return filepath