diff --git a/SportsTime/Core/Services/CloudKitService.swift b/SportsTime/Core/Services/CloudKitService.swift index 1a1ff43..844ba75 100644 --- a/SportsTime/Core/Services/CloudKitService.swift +++ b/SportsTime/Core/Services/CloudKitService.swift @@ -213,9 +213,15 @@ actor CloudKitService { // MARK: - Sync Fetch Methods (return canonical IDs directly from CloudKit) - /// Fetch stadiums with canonical IDs for sync operations - func fetchStadiumsForSync() async throws -> [SyncStadium] { - let predicate = NSPredicate(value: true) + /// Fetch stadiums for sync operations + /// - Parameter lastSync: If nil, fetches all stadiums. If provided, fetches only stadiums modified since that date. + func fetchStadiumsForSync(since lastSync: Date?) async throws -> [SyncStadium] { + let predicate: NSPredicate + if let lastSync = lastSync { + predicate = NSPredicate(format: "modificationDate >= %@", lastSync as NSDate) + } else { + predicate = NSPredicate(value: true) + } let query = CKQuery(recordType: CKRecordType.stadium, predicate: predicate) let (results, _) = try await publicDatabase.records(matching: query) @@ -230,9 +236,15 @@ actor CloudKitService { } } - /// Fetch teams with canonical IDs for sync operations - func fetchTeamsForSync(for sport: Sport) async throws -> [SyncTeam] { - let predicate = NSPredicate(format: "sport == %@", sport.rawValue) + /// Fetch teams for sync operations + /// - Parameter lastSync: If nil, fetches all teams. If provided, fetches only teams modified since that date. + func fetchTeamsForSync(since lastSync: Date?) async throws -> [SyncTeam] { + let predicate: NSPredicate + if let lastSync = lastSync { + predicate = NSPredicate(format: "modificationDate >= %@", lastSync as NSDate) + } else { + predicate = NSPredicate(value: true) + } let query = CKQuery(recordType: CKRecordType.team, predicate: predicate) let (results, _) = try await publicDatabase.records(matching: query) @@ -248,56 +260,43 @@ actor CloudKitService { } } - /// Fetch games with canonical IDs for sync operations - func fetchGamesForSync( - sports: Set, - startDate: Date, - endDate: Date - ) async throws -> [SyncGame] { - var allGames: [SyncGame] = [] - - for sport in sports { - let predicate = NSPredicate( - format: "sport == %@ AND dateTime >= %@ AND dateTime <= %@", - sport.rawValue, - startDate as NSDate, - endDate as NSDate - ) - let query = CKQuery(recordType: CKRecordType.game, predicate: predicate) - - let (results, _) = try await publicDatabase.records(matching: query) - - let games = results.compactMap { result -> SyncGame? in - guard case .success(let record) = result.1 else { return nil } - let ckGame = CKGame(record: record) - - // Extract canonical IDs directly from CloudKit - guard let canonicalId = ckGame.canonicalId, - let homeTeamCanonicalId = ckGame.homeTeamCanonicalId, - let awayTeamCanonicalId = ckGame.awayTeamCanonicalId, - let stadiumCanonicalId = ckGame.stadiumCanonicalId - else { return nil } - - // For the Game domain object, use canonical IDs directly - guard let game = ckGame.game( - homeTeamId: homeTeamCanonicalId, - awayTeamId: awayTeamCanonicalId, - stadiumId: stadiumCanonicalId - ) else { return nil } - - return SyncGame( - game: game, - canonicalId: canonicalId, - homeTeamCanonicalId: homeTeamCanonicalId, - awayTeamCanonicalId: awayTeamCanonicalId, - stadiumCanonicalId: stadiumCanonicalId - ) - } - - allGames.append(contentsOf: games) + /// Fetch games for sync operations + /// - Parameter lastSync: If nil, fetches all games. If provided, fetches only games modified since that date. + func fetchGamesForSync(since lastSync: Date?) async throws -> [SyncGame] { + let predicate: NSPredicate + if let lastSync = lastSync { + predicate = NSPredicate(format: "modificationDate >= %@", lastSync as NSDate) + } else { + predicate = NSPredicate(value: true) } + let query = CKQuery(recordType: CKRecordType.game, predicate: predicate) - return allGames.sorted { $0.game.dateTime < $1.game.dateTime } + let (results, _) = try await publicDatabase.records(matching: query) + + return results.compactMap { result -> SyncGame? in + guard case .success(let record) = result.1 else { return nil } + let ckGame = CKGame(record: record) + + guard let canonicalId = ckGame.canonicalId, + let homeTeamCanonicalId = ckGame.homeTeamCanonicalId, + let awayTeamCanonicalId = ckGame.awayTeamCanonicalId, + let stadiumCanonicalId = ckGame.stadiumCanonicalId + else { return nil } + + guard let game = ckGame.game( + homeTeamId: homeTeamCanonicalId, + awayTeamId: awayTeamCanonicalId, + stadiumId: stadiumCanonicalId + ) else { return nil } + + return SyncGame( + game: game, + canonicalId: canonicalId, + homeTeamCanonicalId: homeTeamCanonicalId, + awayTeamCanonicalId: awayTeamCanonicalId, + stadiumCanonicalId: stadiumCanonicalId + ) + }.sorted { $0.game.dateTime < $1.game.dateTime } } // MARK: - League Structure & Team Aliases