import Foundation import SwiftUI // MARK: - Training Plan struct TrainingPlan: Identifiable, Equatable, Codable { let id: String let title: String let description: String let planType: PlanType let durationWeeks: Int let difficulty: Difficulty let startDate: Date let endDate: Date let weeklyWorkouts: [WeeklyWorkout] var progress: PlanProgress var isFollowing: Bool let createdAt: Date enum CodingKeys: String, CodingKey { case id, title, description, planType, durationWeeks, difficulty, startDate, endDate, weeklyWorkouts, progress, isFollowing, createdAt } init( id: String, title: String, description: String, planType: PlanType, durationWeeks: Int, difficulty: Difficulty, startDate: Date, endDate: Date, weeklyWorkouts: [WeeklyWorkout], progress: PlanProgress, isFollowing: Bool, createdAt: Date ) { self.id = id self.title = title self.description = description self.planType = planType self.durationWeeks = durationWeeks self.difficulty = difficulty self.startDate = startDate self.endDate = endDate self.weeklyWorkouts = weeklyWorkouts self.progress = progress self.isFollowing = isFollowing self.createdAt = createdAt } static func == (lhs: TrainingPlan, rhs: TrainingPlan) -> Bool { lhs.id == rhs.id } } // MARK: - Plan Type enum PlanType: String, CaseIterable, Codable { case fiveK = "5K" case tenK = "10K" case halfMarathon = "HALF_MARATHON" case fullMarathon = "FULL_MARATHON" case custom = "CUSTOM" var displayName: String { switch self { case .fiveK: return "5K" case .tenK: return "10K" case .halfMarathon: return "Half Marathon" case .fullMarathon: return "Full Marathon" case .custom: return "Custom" } } var distanceKm: Double { switch self { case .fiveK: return 5.0 case .tenK: return 10.0 case .halfMarathon: return 21.1 case .fullMarathon: return 42.2 case .custom: return 0.0 } } var icon: String { switch self { case .fiveK: return "figure.run" case .tenK: return "figure.run" case .halfMarathon: return "flag.fill" case .fullMarathon: return "flag.fill" case .custom: return "wrench.and.screwdriver" } } } // MARK: - Difficulty enum Difficulty: String, CaseIterable, Codable { case beginner case intermediate case advanced case elite var displayName: String { switch self { case .beginner: return "Beginner" case .intermediate: return "Intermediate" case .advanced: return "Advanced" case .elite: return "Elite" } } var color: Color { switch self { case .beginner: return .green case .intermediate: return .blue case .advanced: return .orange case .elite: return .red } } } // MARK: - Weekly Workout struct WeeklyWorkout: Identifiable, Codable { let id: String let weekNumber: Int let dailySessions: [DailySession] var completedSessions: Int { dailySessions.filter { $0.status == .completed }.count } var totalSessions: Int { dailySessions.count } var progressPercentage: Double { totalSessions == 0 ? 0 : Double(completedSessions) / Double(totalSessions) * 100 } } // MARK: - Daily Session struct DailySession: Identifiable, Codable { let id: String let dayOfWeek: DayOfWeek let workoutType: WorkoutType let title: String let description: String let targetDistanceKm: Double? let targetDurationMinutes: Int? let targetPaceMinPerKm: Double? let intensity: Intensity var status: SessionStatus var completedDistanceKm: Double? var completedDurationMinutes: Int? enum CodingKeys: String, CodingKey { case id, dayOfWeek, workoutType, title, description, targetDistanceKm, targetDurationMinutes, targetPaceMinPerKm, intensity, status, completedDistanceKm, completedDurationMinutes } } // MARK: - Day of Week enum DayOfWeek: String, CaseIterable, Codable { case monday, tuesday, wednesday, thursday, friday, saturday, sunday var displayName: String { switch self { case .monday: return "Mon" case .tuesday: return "Tue" case .wednesday: return "Wed" case .thursday: return "Thu" case .friday: return "Fri" case .saturday: return "Sat" case .sunday: return "Sun" } } } // MARK: - Workout Type enum WorkoutType: String, CaseIterable, Codable { case easyRun case tempoRun case intervalTraining case longRun case speedWork case recoveryRun case crossTraining case rest var displayName: String { switch self { case .easyRun: return "Easy Run" case .tempoRun: return "Tempo Run" case .intervalTraining: return "Intervals" case .longRun: return "Long Run" case .speedWork: return "Speed Work" case .recoveryRun: return "Recovery Run" case .crossTraining: return "Cross Train" case .rest: return "Rest" } } var icon: String { switch self { case .easyRun: return "figure.walk" case .tempoRun: return "figure.run" case .intervalTraining: return "bolt.fill" case .longRun: return "figure.run" case .speedWork: return "speedometer" case .recoveryRun: return "leaf.fill" case .crossTraining: return "dumbbell.fill" case .rest: return "moon.fill" } } var color: Color { switch self { case .easyRun: return .green case .tempoRun: return .blue case .intervalTraining: return .purple case .longRun: return .orange case .speedWork: return .red case .recoveryRun: return .mint case .crossTraining: return .gray case .rest: return .secondary } } } // MARK: - Intensity enum Intensity: String, CaseIterable, Codable { case veryEasy case easy case moderate case hard case veryHard var displayName: String { switch self { case .veryEasy: return "Very Easy" case .easy: return "Easy" case .moderate: return "Moderate" case .hard: return "Hard" case .veryHard: return "Very Hard" } } } // MARK: - Session Status enum SessionStatus: String, CaseIterable, Codable { case pending case inProgress case completed case skipped } // MARK: - Plan Progress struct PlanProgress: Codable { let completedWeeks: Int let totalWeeks: Int let completedSessions: Int let totalSessions: Int let currentWeekNumber: Int var percentage: Double { totalWeeks == 0 ? 0 : Double(completedWeeks) / Double(totalWeeks) * 100 } var sessionPercentage: Double { totalSessions == 0 ? 0 : Double(completedSessions) / Double(totalSessions) * 100 } } // MARK: - AI Plan Generation Request struct GeneratePlanRequest: Encodable { let planType: PlanType let difficulty: Difficulty let startDate: Date let currentWeeklyMileageKm: Double? let goalTimeMinutes: Int? let availableDays: [DayOfWeek] } // MARK: - API Response Types struct TrainingPlanListResponse: Decodable { let plans: [TrainingPlan] let hasMore: Bool } struct TrainingPlanDetailResponse: Decodable { let plan: TrainingPlan } struct GeneratePlanResponse: Decodable { let plan: TrainingPlan } struct UpdateSessionStatusResponse: Decodable { let success: Bool let sessionId: String let status: SessionStatus }