import Foundation import SwiftData /// Builds starter Splits from the bundled YAML exercise catalog, grouped by the /// catalog's `split` label (Upper Body / Core / Lower Body). Written on demand /// (never auto-seeded) through the SyncEngine — an empty cache at launch can't be /// told apart from an iCloud library that simply hasn't downloaded yet. enum SplitSeeder { /// Visual theme per starter split group, in display order. private static let groups: [(name: String, color: String, icon: String)] = [ ("Upper Body", "blue", "figure.strengthtraining.traditional"), ("Core", "orange", "figure.core.training"), ("Lower Body", "green", "figure.run"), ] /// Default split source catalog (most universally applicable). private static let sourceFile = "bodyweight-starter.exercises.yaml" /// Builds the default split documents (fresh ULIDs each call). static func defaultSplitDocuments() -> [SplitDocument] { let lists = ExerciseListLoader.loadExerciseLists() guard let catalog = lists[sourceFile] else { return [] } var docs: [SplitDocument] = [] for (order, group) in groups.enumerated() { let items = catalog.exercises.filter { $0.split == group.name } guard !items.isEmpty else { continue } let exercises = items.enumerated().map { idx, item in ExerciseDocument( id: ULID.make(), name: item.name, order: idx, sets: 3, reps: 10, weight: 0, loadType: LoadType.weight.rawValue, durationSeconds: 0, weightLastUpdated: nil, weightReminderWeeks: 2 ) } docs.append(SplitDocument( schemaVersion: SplitDocument.currentSchema, id: ULID.make(), name: group.name, color: group.color, systemImage: group.icon, order: order, createdAt: Date(), updatedAt: Date(), exercises: exercises )) } return docs } /// Writes any starter splits whose name doesn't already exist, appended after /// existing splits. Idempotent against double-taps / partial prior seeds. @MainActor static func seedDefaults(into context: ModelContext, using sync: SyncEngine) async { let existing = (try? context.fetch(FetchDescriptor())) ?? [] let existingNames = Set(existing.map(\.name)) let base = existing.count let fresh = defaultSplitDocuments().filter { !existingNames.contains($0.name) } for (offset, var doc) in fresh.enumerated() { doc.order = base + offset await sync.save(split: doc) } } }