import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:trainhub_flutter/injection.dart'; import 'package:trainhub_flutter/domain/repositories/chat_repository.dart'; import 'package:trainhub_flutter/presentation/chat/chat_state.dart'; part 'chat_controller.g.dart'; @riverpod class ChatController extends _$ChatController { late final ChatRepository _repo; @override Future build() async { _repo = getIt(); final sessions = await _repo.getAllSessions(); return ChatState(sessions: sessions); } Future createSession() async { final session = await _repo.createSession(); final sessions = await _repo.getAllSessions(); state = AsyncValue.data( ChatState(sessions: sessions, activeSession: session), ); } Future loadSession(String id) async { final session = await _repo.getSession(id); if (session == null) return; final messages = await _repo.getMessages(id); final current = state.valueOrNull ?? const ChatState(); state = AsyncValue.data( current.copyWith(activeSession: session, messages: messages), ); } Future deleteSession(String id) async { await _repo.deleteSession(id); final sessions = await _repo.getAllSessions(); final current = state.valueOrNull ?? const ChatState(); state = AsyncValue.data( current.copyWith( sessions: sessions, activeSession: current.activeSession?.id == id ? null : current.activeSession, messages: current.activeSession?.id == id ? [] : current.messages, ), ); } Future sendMessage(String content) async { final current = state.valueOrNull; if (current == null) return; String sessionId; if (current.activeSession == null) { final session = await _repo.createSession(); sessionId = session.id; final sessions = await _repo.getAllSessions(); state = AsyncValue.data( current.copyWith(sessions: sessions, activeSession: session), ); } else { sessionId = current.activeSession!.id; } await _repo.addMessage( sessionId: sessionId, role: 'user', content: content, ); final messagesAfterUser = await _repo.getMessages(sessionId); state = AsyncValue.data( state.valueOrNull!.copyWith(messages: messagesAfterUser, isTyping: true), ); await Future.delayed(const Duration(seconds: 1)); final String response = _getMockResponse(content); await _repo.addMessage( sessionId: sessionId, role: 'assistant', content: response, ); final messagesAfterAi = await _repo.getMessages(sessionId); if (messagesAfterAi.length <= 2) { final title = content.length > 30 ? '${content.substring(0, 30)}...' : content; await _repo.updateSessionTitle(sessionId, title); } final sessions = await _repo.getAllSessions(); state = AsyncValue.data( state.valueOrNull!.copyWith( messages: messagesAfterAi, isTyping: false, sessions: sessions, ), ); } String _getMockResponse(String input) { final String lower = input.toLowerCase(); if (lower.contains('plan') || lower.contains('program')) { return "I can help you design a training plan! What are your goals? Strength, hypertrophy, or endurance?"; } else if (lower.contains('squat') || lower.contains('bench')) { return "Compound movements are great. Remember to maintain proper form. For squats, keep your chest up and knees tracking over toes."; } else if (lower.contains('nutrition') || lower.contains('eat')) { return "Nutrition is key. Aim for 1.6-2.2g of protein per kg of bodyweight if you're training hard."; } return "I'm your AI training assistant. How can I help you today?"; } }