import Foundation import SwiftUI @MainActor class FamilyPlanViewModel: ObservableObject { @Published var familyPlan: FamilyPlan? @Published var leaderboard: [FamilyLeaderboardEntry] = [] @Published var selectedMetric: LeaderboardMetric = .distance @Published var isLoading: Bool = false @Published var error: FamilyPlanError? private let service: FamilyPlanServiceProtocol init(service: FamilyPlanServiceProtocol = FamilyPlanService()) { self.service = service } func fetchFamilyPlan() async { isLoading = true error = nil defer { isLoading = false } do { familyPlan = try await service.getFamilyPlan() } catch let error as FamilyPlanError { self.error = error } catch { print("Failed to fetch family plan: \(error)") } } func inviteMember(email: String, name: String) async { guard let plan = familyPlan, plan.availableSlots > 0 else { return } let request = InviteMemberRequest(email: email, name: name) do { try await service.inviteMember(request: request) objectWillChange.send() } catch { print("Failed to invite member: \(error)") } } func removeMember(id: String) async { guard let index = familyPlan?.members.firstIndex(where: { $0.id == id }) else { return } do { try await service.removeMember(id: id) familyPlan?.members.remove(at: index) objectWillChange.send() } catch { print("Failed to remove member: \(error)") } } func fetchLeaderboard() async { isLoading = true error = nil defer { isLoading = false } do { leaderboard = try await service.getLeaderboard(metric: selectedMetric) } catch let error as FamilyPlanError { self.error = error } catch { print("Failed to fetch leaderboard: \(error)") } } var activeMembers: [FamilyMember] { familyPlan?.members.filter { $0.role == .member || $0.role == .owner } ?? [] } var pendingInvites: [FamilyMember] { familyPlan?.members.filter { $0.role == .pending } ?? [] } var metrics: [LeaderboardMetric] { LeaderboardMetric.allCases } }