import 'dart:typed_data'; import 'package:flutter/services.dart'; import 'package:pdf/pdf.dart'; import 'package:pdf/widgets.dart' as pw; import 'package:printing/printing.dart'; import 'package:intl/intl.dart'; import '../models/user_profile.dart'; import '../models/cycle_entry.dart'; class PdfService { static Future generateCycleReport(UserProfile? user, List entries) async { final pdf = pw.Document(); final font = await PdfGoogleFonts.outfitRegular(); final boldFont = await PdfGoogleFonts.outfitBold(); // Group entries by month final entriesByMonth = >{}; for (var entry in entries) { final month = DateFormat('MMMM yyyy').format(entry.date); if (!entriesByMonth.containsKey(month)) { entriesByMonth[month] = []; } entriesByMonth[month]!.add(entry); } pdf.addPage( pw.MultiPage( pageFormat: PdfPageFormat.a4, theme: pw.ThemeData.withFont( base: font, bold: boldFont, ), build: (pw.Context context) { return [ pw.Header( level: 0, child: pw.Row( mainAxisAlignment: pw.MainAxisAlignment.spaceBetween, children: [ pw.Text('Cycle Report', style: pw.TextStyle(fontSize: 24, fontWeight: pw.FontWeight.bold)), pw.Text(DateFormat.yMMMd().format(DateTime.now()), style: const pw.TextStyle(color: PdfColors.grey)), ], ), ), if (user != null) pw.Padding( padding: const pw.EdgeInsets.only(bottom: 20), child: pw.Column( crossAxisAlignment: pw.CrossAxisAlignment.start, children: [ pw.Text('Name: ${user.name}'), pw.Text('Average Cycle Length: ${user.averageCycleLength} days'), pw.Text('Average Period Length: ${user.averagePeriodLength} days'), ], ), ), ...entriesByMonth.entries.map((entry) { final month = entry.key; final monthEntries = entry.value; // Sort by date monthEntries.sort((a, b) => a.date.compareTo(b.date)); return pw.Column( crossAxisAlignment: pw.CrossAxisAlignment.start, children: [ pw.SizedBox(height: 10), pw.Text(month, style: pw.TextStyle(fontSize: 18, fontWeight: pw.FontWeight.bold, color: PdfColors.blueGrey800)), pw.SizedBox(height: 5), pw.Table.fromTextArray( context: context, headerStyle: pw.TextStyle(fontWeight: pw.FontWeight.bold), headers: ['Date', 'Phase', 'Details', 'Notes'], data: monthEntries.map((e) { final details = []; if (e.isPeriodDay) details.add('Period'); if (e.mood != null) details.add('Mood: ${e.mood!.label}'); if (e.symptomCount > 0) details.add('${e.symptomCount} symptoms'); return [ DateFormat('d, E').format(e.date), '${e.isPeriodDay ? "Menstrual" : "-"}', // Simplified for report details.join(', '), e.notes ?? '', ]; }).toList(), columnWidths: { 0: const pw.FlexColumnWidth(1), 1: const pw.FlexColumnWidth(1), 2: const pw.FlexColumnWidth(2), 3: const pw.FlexColumnWidth(2), }, ), pw.SizedBox(height: 15), ], ); }), ]; }, ), ); await Printing.sharePdf(bytes: await pdf.save(), filename: 'cycle_report.pdf'); } }