import 'dart:developer'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:equatable/equatable.dart'; import 'package:chat_repository/chat_repository.dart'; part 'chat_event.dart'; part 'chat_state.dart'; class ChatBloc extends Bloc { final ApiChatRepository _chatRepository; /// Resolved once per conversation. Every chat endpoint is keyed by the chat /// id, which the app used to confuse with the service id. String? _chatId; ChatBloc({ required ApiChatRepository chatRepository, }) : _chatRepository = chatRepository, super(ChatInitial()) { on(_onLoadChatEvent); on(_onSendMessageEvent); } void _onLoadChatEvent(LoadChatEvent event, Emitter emit) async { emit(ChatLoading()); try { final chat = await _chatRepository.loadConversation(event.professionalId); _chatId = chat.id; emit(ChatLoaded(chat: chat)); } catch (e) { log(e.toString()); emit(ChatFailure()); } } void _onSendMessageEvent( SendMessageEvent event, Emitter emit) async { final current = state; // Show the message immediately; the reload below reconciles with the // backend. Previously nothing was emitted at all and the message vanished. if (current is ChatLoaded) { emit(ChatLoaded( chat: ChatEntity( id: current.chat.id, userId: current.chat.userId, professionalId: current.chat.professionalId, messages: [...current.chat.messages, event.message], ), )); } try { final chatId = _chatId; if (chatId == null || chatId.isEmpty) { throw Exception('El chat aún no está abierto'); } await _chatRepository.sendMessage(chatId, event.message); final messages = await _chatRepository.fetchMessages(chatId); emit(ChatLoaded( chat: ChatEntity( id: chatId, userId: current is ChatLoaded ? current.chat.userId : '', professionalId: current is ChatLoaded ? current.chat.professionalId : '', messages: messages, ), )); } catch (e) { log(e.toString()); // Roll the optimistic message back so nobody believes it was delivered. if (current is ChatLoaded) emit(ChatLoaded(chat: current.chat)); emit(SendMessageFailure()); } } }