import 'dart:io'; import 'package:intl/intl.dart'; import 'package:path_provider/path_provider.dart'; import 'package:open_filex/open_filex.dart'; import '../models/cycle_entry.dart'; import '../models/user_profile.dart'; import 'cycle_service.dart'; import 'package:uuid/uuid.dart'; class IcsService { static Future generateCycleCalendar(List entries, {UserProfile? user, bool includePredictions = true}) async { final buffer = StringBuffer(); buffer.writeln('BEGIN:VCALENDAR'); buffer.writeln('VERSION:2.0'); buffer.writeln('PRODID:-//Christian Period Tracker//Cycle Calendar//EN'); // Sort entries entries.sort((a, b) => a.date.compareTo(b.date)); // 1. Logged Entries for (var entry in entries) { if (entry.isPeriodDay) { final dateStr = DateFormat('yyyyMMdd').format(entry.date); buffer.writeln('BEGIN:VEVENT'); buffer.writeln('UID:${entry.id}'); buffer.writeln('DTSTAMP:${DateFormat('yyyyMMddTHHmmss').format(DateTime.now())}Z'); buffer.writeln('DTSTART;VALUE=DATE:$dateStr'); // All day event buffer.writeln('DTEND;VALUE=DATE:${DateFormat('yyyyMMdd').format(entry.date.add(const Duration(days: 1)))}'); buffer.writeln('SUMMARY:Period'); buffer.writeln('DESCRIPTION:Logged period day.'); buffer.writeln('END:VEVENT'); } } // 2. Predicted Entries if (includePredictions && user != null) { final predictedDays = CycleService.predictNextPeriodDays(user); for (var date in predictedDays) { final dateStr = DateFormat('yyyyMMdd').format(date); final uuid = const Uuid().v4(); buffer.writeln('BEGIN:VEVENT'); buffer.writeln('UID:$uuid'); buffer.writeln('DTSTAMP:${DateFormat('yyyyMMddTHHmmss').format(DateTime.now())}Z'); buffer.writeln('DTSTART;VALUE=DATE:$dateStr'); buffer.writeln('DTEND;VALUE=DATE:${DateFormat('yyyyMMdd').format(date.add(const Duration(days: 1)))}'); buffer.writeln('SUMMARY:Predicted Period'); buffer.writeln('DESCRIPTION:Predicted period day based on cycle history.'); buffer.writeln('STATUS:TENTATIVE'); // Mark as tentative buffer.writeln('END:VEVENT'); } } buffer.writeln('END:VCALENDAR'); // Save to file final directory = await getApplicationDocumentsDirectory(); final file = File('${directory.path}/cycle_calendar.ics'); await file.writeAsString(buffer.toString()); // Open/Share file final result = await OpenFilex.open(file.path); if (result.type != ResultType.done) { throw 'Could not open file: ${result.message}'; } } }