// // PollDetailViewModel.swift // SportsTime // // ViewModel for viewing poll details and results // import Foundation import SwiftUI @Observable @MainActor final class PollDetailViewModel { var poll: TripPoll? var votes: [PollVote] = [] var myVote: PollVote? var isLoading = false var isRefreshing = false var error: PollError? private let pollService = PollService.shared var results: PollResults? { guard let poll else { return nil } return PollResults(poll: poll, votes: votes) } func checkIsOwner() async -> Bool { guard let poll else { return false } do { let userId = try await pollService.getCurrentUserRecordID() return poll.ownerId == userId } catch { return false } } var isOwner: Bool { get async { await checkIsOwner() } } var hasVoted: Bool { myVote != nil } var shareURL: URL? { poll?.shareURL } func loadPoll(byId pollId: UUID) async { isLoading = true error = nil do { async let pollTask = pollService.fetchPoll(byId: pollId) async let votesTask = pollService.fetchVotes(forPollId: pollId) async let myVoteTask = pollService.fetchMyVote(forPollId: pollId) let (fetchedPoll, fetchedVotes, fetchedMyVote) = try await (pollTask, votesTask, myVoteTask) self.poll = fetchedPoll self.votes = fetchedVotes self.myVote = fetchedMyVote // Subscribe to vote updates try? await pollService.subscribeToVoteUpdates(forPollId: pollId) } catch let pollError as PollError { error = pollError } catch { self.error = .unknown(error) } isLoading = false } func loadPoll(byShareCode shareCode: String) async { isLoading = true error = nil do { let fetchedPoll = try await pollService.fetchPoll(byShareCode: shareCode) self.poll = fetchedPoll // Now fetch votes with the poll ID async let votesTask = pollService.fetchVotes(forPollId: fetchedPoll.id) async let myVoteTask = pollService.fetchMyVote(forPollId: fetchedPoll.id) let (fetchedVotes, fetchedMyVote) = try await (votesTask, myVoteTask) self.votes = fetchedVotes self.myVote = fetchedMyVote // Subscribe to vote updates try? await pollService.subscribeToVoteUpdates(forPollId: fetchedPoll.id) } catch let pollError as PollError { error = pollError } catch { self.error = .unknown(error) } isLoading = false } /// Load poll from an existing object (avoids CloudKit fetch delay) func loadPoll(from existingPoll: TripPoll) async { isLoading = true error = nil self.poll = existingPoll do { // Still fetch votes and subscription from CloudKit async let votesTask = pollService.fetchVotes(forPollId: existingPoll.id) async let myVoteTask = pollService.fetchMyVote(forPollId: existingPoll.id) let (fetchedVotes, fetchedMyVote) = try await (votesTask, myVoteTask) self.votes = fetchedVotes self.myVote = fetchedMyVote // Subscribe to vote updates try? await pollService.subscribeToVoteUpdates(forPollId: existingPoll.id) } catch { // Votes fetch failed, but we have the poll - non-critical error self.votes = [] } isLoading = false } func refresh() async { guard let poll else { return } isRefreshing = true do { async let votesTask = pollService.fetchVotes(forPollId: poll.id) async let myVoteTask = pollService.fetchMyVote(forPollId: poll.id) let (fetchedVotes, fetchedMyVote) = try await (votesTask, myVoteTask) self.votes = fetchedVotes self.myVote = fetchedMyVote } catch { // Silently fail refresh - user can pull to refresh again } isRefreshing = false } func deletePoll() async -> Bool { guard let poll else { return false } isLoading = true error = nil do { try await pollService.deletePoll(poll.id) try? await pollService.unsubscribeFromVoteUpdates() self.poll = nil return true } catch let pollError as PollError { error = pollError } catch { self.error = .unknown(error) } isLoading = false return false } func cleanup() async { try? await pollService.unsubscribeFromVoteUpdates() } }