// // AIReport.swift // Reflect // // Data models for AI-generated mood reports with PDF export. // import Foundation import FoundationModels // MARK: - Report Type enum ReportType: String, CaseIterable { case quickSummary = "Quick Summary" case detailed = "Detailed Report" var icon: String { switch self { case .quickSummary: return "doc.text" case .detailed: return "doc.text.magnifyingglass" } } var description: String { switch self { case .quickSummary: return "AI overview of your mood patterns" case .detailed: return "Week-by-week analysis with full data" } } } // MARK: - Report Entry (decoupled from SwiftData) struct ReportEntry { let date: Date let mood: Mood let notes: String? let weather: WeatherData? let reflection: GuidedReflection? init(from model: MoodEntryModel) { self.date = model.forDate self.mood = model.mood self.notes = model.notes self.weather = model.weatherJSON.flatMap { WeatherData.decode(from: $0) } self.reflection = model.reflectionJSON.flatMap { GuidedReflection.decode(from: $0) } } } // MARK: - Report Overview Stats struct ReportOverviewStats { let totalEntries: Int let averageMood: Double let moodDistribution: [Mood: Int] let trend: String let dateRange: String } // MARK: - Report Week struct ReportWeek: Identifiable { let id = UUID() let weekNumber: Int let startDate: Date let endDate: Date let entries: [ReportEntry] var aiSummary: String? } // MARK: - Report Month Summary struct ReportMonthSummary: Identifiable { let id = UUID() let month: Int let year: Int let entryCount: Int let averageMood: Double var aiSummary: String? var title: String { let formatter = DateFormatter() formatter.dateFormat = "MMMM yyyy" var components = DateComponents() components.month = month components.year = year let date = Calendar.current.date(from: components) ?? Date() return formatter.string(from: date) } } // MARK: - Report Year Summary struct ReportYearSummary: Identifiable { let id = UUID() let year: Int let entryCount: Int let averageMood: Double var aiSummary: String? } // MARK: - Assembled Report struct MoodReport { let reportType: ReportType let generatedAt: Date let overview: ReportOverviewStats let weeks: [ReportWeek] let monthlySummaries: [ReportMonthSummary] let yearlySummaries: [ReportYearSummary] var quickSummary: String? } // MARK: - @Generable AI Response Structs @available(iOS 26, *) @Generable struct AIWeeklySummary: Equatable { @Guide(description: "A clinical, factual summary of the user's mood patterns for this week. Use third-person perspective (e.g., 'The individual'). 2-3 sentences covering mood trends, notable patterns, and any significant changes. Neutral, professional tone suitable for a therapist to read.") var summary: String } @available(iOS 26, *) @Generable struct AIMonthSummary: Equatable { @Guide(description: "A clinical, factual summary of the user's mood patterns for this month. Use third-person perspective. 3-4 sentences covering overall mood trend, week-over-week changes, and notable patterns. Professional tone suitable for clinical review.") var summary: String } @available(iOS 26, *) @Generable struct AIYearSummary: Equatable { @Guide(description: "A clinical, factual summary of the user's mood patterns for this year. Use third-person perspective. 3-5 sentences covering seasonal patterns, long-term trends, and significant periods. Professional tone suitable for clinical review.") var summary: String } @available(iOS 26, *) @Generable struct AIQuickSummaryResponse: Equatable { @Guide(description: "A comprehensive clinical summary of the user's mood data for the selected period. Use third-person perspective (e.g., 'The individual'). 4-6 sentences covering: overall mood patterns, notable trends, day-of-week patterns, and any areas of concern or improvement. Factual, neutral, professional tone suitable for sharing with a therapist.") var summary: String @Guide(description: "2-3 key clinical observations as brief bullet points. Each should be a single factual sentence about a pattern or trend observed in the data.") var keyObservations: [String] @Guide(description: "1-2 brief, neutral recommendations based on observed patterns. Frame as observations rather than prescriptions (e.g., 'Mood data suggests weekday routines may benefit from...').") var recommendations: [String] }