// // VehicleService.swift // AutoCatCore // // Created by Selim Mustafaev on 19.01.2025. // Copyright © 2025 Selim Mustafaev. All rights reserved. // import Foundation public typealias VehicleWithErrors = ( vehicle: VehicleDto, errors: [Error] ) public final class VehicleService { let apiService: ApiServiceProtocol let storageService: StorageServiceProtocol let locationService: LocationServiceProtocol public init(apiService: ApiServiceProtocol, storageService: StorageServiceProtocol, locationService: LocationServiceProtocol) { self.apiService = apiService self.storageService = storageService self.locationService = locationService } } extension VehicleService: VehicleServiceProtocol { func check( number: String, forceUpdate: Bool, trackLocation: Bool, additionalEvent: VehicleEventDto?, dbUpdatePolicy: DbUpdatePolicy ) async throws -> VehicleWithErrors { var vehicle = (try? await storageService.loadVehicle(number: number)) ?? VehicleDto(number: number) var errors: [Error] = [] let notes = vehicle.notes let events: [VehicleEventDto] if let additionalEvent, !vehicle.events.contains(where: { $0.id == additionalEvent.id }) { events = vehicle.events + [additionalEvent] } else { events = vehicle.events } if additionalEvent != nil { vehicle.events = events vehicle.updatedDate = Date().timeIntervalSince1970 vehicle.synchronized = false } async let locationTask = trackLocation ? locationService.getRecentLocation() : nil async let vehicleTask = apiService.checkVehicle(by: number, notes: notes, events: events, force: forceUpdate) do { vehicle = try await vehicleTask } catch { errors.append(error) } if trackLocation { do { if let event = try await locationTask { vehicle.events.append(event) vehicle.updatedDate = Date().timeIntervalSince1970 vehicle.synchronized = false if !vehicle.unrecognized { vehicle = try await apiService.add(event: event, to: number) } } } catch { errors.append(error) } } await locationService.resetLastEvent() try await storageService.updateVehicle(dto: vehicle, policy: dbUpdatePolicy) return VehicleWithErrors(vehicle: vehicle, errors: errors) } public func check(number: String, trackLocation: Bool) async throws -> VehicleWithErrors { #if targetEnvironment(macCatalyst) try await check( number: number, forceUpdate: false, trackLocation: false, additionalEvent: nil, dbUpdatePolicy: .always ) #else try await check( number: number, forceUpdate: false, trackLocation: trackLocation, additionalEvent: nil, dbUpdatePolicy: .always ) #endif } public func updateHistory(number: String) async throws -> VehicleWithErrors { try await check( number: number, forceUpdate: true, trackLocation: false, additionalEvent: nil, dbUpdatePolicy: .always ) } public func updateSearch(number: String) async throws -> VehicleWithErrors { try await check( number: number, forceUpdate: true, trackLocation: false, additionalEvent: nil, dbUpdatePolicy: .ifExists ) } public func checkRecord(number: String, event: VehicleEventDto?) async throws -> VehicleWithErrors { try await check( number: number, forceUpdate: false, trackLocation: false, additionalEvent: event, dbUpdatePolicy: .always ) } }