import Foundation final class PrivateChatsViewModel: ObservableObject { @Published private(set) var chats: [PrivateChatListItem] = [] @Published private(set) var isInitialLoading: Bool = false @Published private(set) var isLoadingMore: Bool = false @Published var errorMessage: String? private let chatService: ChatService private let pageSize: Int private var offset: Int = 0 private var hasMore: Bool = true init(chatService: ChatService = ChatService(), pageSize: Int = 20) { self.chatService = chatService self.pageSize = pageSize } func loadInitialChats(force: Bool = false) { guard !isInitialLoading else { return } if !force && !chats.isEmpty { return } isInitialLoading = true errorMessage = nil let previousOffset = offset let previousHasMore = hasMore offset = 0 hasMore = true chatService.fetchPrivateChats(offset: 0, limit: pageSize) { [weak self] result in guard let self else { return } self.isInitialLoading = false switch result { case .success(let data): self.chats = data.items self.offset = data.items.count self.hasMore = data.hasMore case .failure(let error): self.errorMessage = self.message(for: error) self.offset = previousOffset self.hasMore = previousHasMore } } } func refresh() { loadInitialChats(force: true) } func loadMoreIfNeeded(currentItem item: PrivateChatListItem) { guard hasMore, !isLoadingMore, item.id == chats.last?.id else { return } isLoadingMore = true chatService.fetchPrivateChats(offset: offset, limit: pageSize) { [weak self] result in guard let self else { return } self.isLoadingMore = false switch result { case .success(let data): self.chats.append(contentsOf: data.items) self.offset = self.chats.count self.hasMore = data.hasMore case .failure(let error): self.errorMessage = self.message(for: error) } } } private func message(for error: Error) -> String { if let chatError = error as? ChatServiceError { return chatError.errorDescription ?? NSLocalizedString("Не удалось загрузить чаты.", comment: "") } if let networkError = error as? NetworkError { switch networkError { case .unauthorized: return NSLocalizedString("Сессия истекла. Войдите снова.", comment: "") case .invalidURL, .noResponse: return NSLocalizedString("Ошибка соединения с сервером.", comment: "") case .network(let underlying): return String(format: NSLocalizedString("Ошибка сети: %@", comment: ""), underlying.localizedDescription) case .server(let statusCode, _): return String(format: NSLocalizedString("Ошибка сервера (%@).", comment: ""), "\(statusCode)") } } return NSLocalizedString("Неизвестная ошибка. Попробуйте позже.", comment: "") } }