import Foundation import Combine final class CreatorChannelViewModel: ObservableObject { private let repository = CreatorChannelHomeRepository() private let userRepository = UserRepository() private let communityRepository = CreatorCommunityRepository() private var subscription = Set() @Published var isLoading = false @Published var response: CreatorChannelHomeResponse? @Published var hasLoaded = false @Published var selectedTab: CreatorChannelTab = .home @Published var isApiFailedPlaceholderVisible = false @Published var errorMessage = "" @Published var isShowPopup = false func fetchHome(creatorId: Int) { isLoading = true isApiFailedPlaceholderVisible = false repository.getHome(creatorId: creatorId) .sink { [weak self] result in guard let self else { return } switch result { case .finished: DEBUG_LOG("finish") case .failure(let error): ERROR_LOG(error.localizedDescription) self.applyApiFailedPlaceholderState() } } receiveValue: { [weak self] response in guard let self else { return } do { if let jsonString = String(data: response.data, encoding: .utf8) { DEBUG_LOG("CreatorChannelHome raw response: \(jsonString)") } let jsonDecoder = JSONDecoder() let decoded = try jsonDecoder.decode(ApiResponse.self, from: response.data) if let data = decoded.data, decoded.success { self.response = data self.selectedTab = .home self.isApiFailedPlaceholderVisible = false } else { if let message = decoded.message { ERROR_LOG(message) } self.applyApiFailedPlaceholderState() } } catch { ERROR_LOG(error.localizedDescription) print(error) self.applyApiFailedPlaceholderState() } self.hasLoaded = true self.isLoading = false } .store(in: &subscription) } func creatorFollow(follow: Bool = true, notify: Bool = true) { guard let creatorId = response?.creator.creatorId else { return } isLoading = true userRepository.creatorFollow(creatorId: creatorId, follow: follow, notify: notify) .sink { [weak self] result in guard let self else { return } switch result { case .finished: DEBUG_LOG("finish") case .failure(let error): ERROR_LOG(error.localizedDescription) self.isLoading = false } } receiveValue: { [weak self] response in guard let self else { return } do { let jsonDecoder = JSONDecoder() let decoded = try jsonDecoder.decode(ApiResponseWithoutData.self, from: response.data) if decoded.success { self.updateCreatorFollowState(isFollow: follow, isNotify: notify) } else { self.errorMessage = decoded.message ?? I18n.Common.commonError self.isShowPopup = true } } catch { ERROR_LOG(error.localizedDescription) self.errorMessage = I18n.Common.commonError self.isShowPopup = true } self.isLoading = false } .store(in: &subscription) } func likeCommunityPost(postId: Int) { guard postId > 0 else { return } communityRepository.communityPostLike(postId: postId) .sink { [weak self] result in guard let self else { return } switch result { case .finished: DEBUG_LOG("finish") case .failure(let error): ERROR_LOG(error.localizedDescription) self.errorMessage = I18n.Common.commonError self.isShowPopup = true } } receiveValue: { _ in } .store(in: &subscription) } func createChatRoom(characterId: Int, onSuccess: @escaping (Int) -> Void) { guard characterId > 0 else { return } isLoading = true repository.createChatRoom(characterId: characterId) .receive(on: DispatchQueue.main) .sink { [weak self] result in switch result { case .finished: DEBUG_LOG("finish") case .failure(let error): ERROR_LOG(error.localizedDescription) self?.isLoading = false } } receiveValue: { [weak self] response in self?.isLoading = false do { let jsonDecoder = JSONDecoder() let decoded = try jsonDecoder.decode(ApiResponse.self, from: response.data) if let data = decoded.data, decoded.success { onSuccess(data.chatRoomId) } else { self?.errorMessage = decoded.message ?? I18n.Common.commonError self?.isShowPopup = true } } catch { ERROR_LOG(error.localizedDescription) self?.errorMessage = I18n.Common.commonError self?.isShowPopup = true } } .store(in: &subscription) } private func applyApiFailedPlaceholderState() { response = nil isApiFailedPlaceholderVisible = true hasLoaded = true isLoading = false } private func updateCreatorFollowState(isFollow: Bool, isNotify: Bool) { response?.creator.isFollow = isFollow response?.creator.isNotify = isNotify } }