import 'package:flutter/material.dart'; import 'package:flutter_animate/flutter_animate.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:go_router/go_router.dart'; import '../../../../core/services/auth_service.dart'; import '../../../../core/utils/logger.dart'; /// Página para gerenciar quizzes (eliminar quizzes feitos) class QuizManagementPage extends StatefulWidget { const QuizManagementPage({super.key}); @override State createState() => _QuizManagementPageState(); } class _QuizManagementPageState extends State { List> _quizHistory = []; bool _loading = true; String _userRole = ''; // Turma seleccionada (null = vista de turmas) String? _selectedClassId; Map _classNames = {}; // classId → name // Search and filter final TextEditingController _searchController = TextEditingController(); DateTime? _selectedDate; @override void initState() { super.initState(); _loadUserRole(); _loadQuizHistory(); } @override void dispose() { _searchController.dispose(); super.dispose(); } Future _selectDate() async { final DateTime? picked = await showDatePicker( context: context, initialDate: _selectedDate ?? DateTime.now(), firstDate: DateTime(2020), lastDate: DateTime.now().add(const Duration(days: 365)), ); if (picked != null) { setState(() => _selectedDate = picked); } } Future _loadUserRole() async { final user = AuthService.currentUser; if (user != null) { final userDoc = await FirebaseFirestore.instance .collection('users') .doc(user.uid) .get(); if (userDoc.exists) { setState(() { _userRole = userDoc.data()?['role'] ?? ''; }); } } } Future _loadQuizHistory() async { try { final user = AuthService.currentUser; if (user == null) return; Query query; if (_userRole == 'teacher') { // Professor: ver todos os quizzes criados query = FirebaseFirestore.instance .collection('teacherQuizzes') .where('teacherId', isEqualTo: user.uid) .orderBy('createdAt', descending: true); } else { // Aluno: ver quizzes criados pelo próprio aluno + conceitos dominados final results = await Future.wait([ FirebaseFirestore.instance .collection('userStats') .doc(user.uid) .get(), FirebaseFirestore.instance .collection('quizHistory') .doc(user.uid) .collection('quizzes') .orderBy('createdAt', descending: true) .get(), ]); final userStatsSnapshot = results[0] as DocumentSnapshot; final studentQuizzesSnapshot = results[1] as QuerySnapshot; List> quizList = []; // Adicionar quizzes criados pelo aluno for (final doc in studentQuizzesSnapshot.docs) { final data = Map.from(doc.data() as Map); data['id'] = doc.id; data['title'] = data['materialName'] ?? 'Quiz sem nome'; data['type'] = 'created'; quizList.add(data); } // Adicionar conceitos dominados if (userStatsSnapshot.exists) { final stats = userStatsSnapshot.data() as Map?; if (stats != null) { final masteredConcepts = (stats['masteredConcepts'] as List?) ?.map((c) => Map.from(c as Map)) .toList() ?? []; for (final concept in masteredConcepts) { quizList.add({ 'id': concept['conceptName'] ?? '', 'title': concept['conceptName'] ?? 'Conceito sem nome', 'score': concept['masteryLevel'] ?? 0, 'totalQuestions': 100, // Simulado 'completedAt': concept['masteredAt'] ?? Timestamp.now(), 'type': 'concept', }); } } } setState(() { _quizHistory = quizList; _loading = false; }); return; } final snapshot = await query.get(); final quizzes = snapshot.docs .map((doc) { final data = Map.from(doc.data() as Map); data['id'] = doc.id; return data; }) .cast>() .toList(); // Obter nomes das disciplinas final classIdSet = {}; for (final q in quizzes) { final ids = (q['classIds'] as List?)?.cast() ?? []; classIdSet.addAll(ids); } final classNamesMap = {}; if (classIdSet.isNotEmpty) { final docs = await Future.wait( classIdSet.map( (id) => FirebaseFirestore.instance.collection('classes').doc(id).get(), ), ); for (final doc in docs.where((d) => d.exists)) { classNamesMap[doc.id] = doc.data()?['name'] as String? ?? doc.id; } } setState(() { _quizHistory = quizzes; _classNames = classNamesMap; _loading = false; }); } catch (e) { Logger.error('Error loading quiz history: $e'); setState(() { _loading = false; }); } } Future _deleteQuiz(String quizId, String quizTitle, String type) async { try { String confirmMessage; String successMessage; if (_userRole == 'teacher') { confirmMessage = 'Tem certeza que deseja eliminar o quiz "$quizTitle"? Esta ação não pode ser desfeita.'; successMessage = 'Quiz eliminado com sucesso!'; } else { if (type == 'created') { confirmMessage = 'Tem certeza que deseja eliminar seu quiz "$quizTitle"?'; successMessage = 'Quiz eliminado com sucesso!'; } else { confirmMessage = 'Tem certeza que deseja remover o conceito "$quizTitle" do seu histórico?'; successMessage = 'Conceito removido com sucesso!'; } } final confirmed = await _showDeleteConfirmation( quizTitle, confirmMessage, ); if (!confirmed) return; if (_userRole == 'teacher') { // Professor: eliminar quiz criado await FirebaseFirestore.instance .collection('teacherQuizzes') .doc(quizId) .delete(); // Também eliminar do histórico de alunos final historySnapshot = await FirebaseFirestore.instance .collection('quizHistory') .where('quizId', isEqualTo: quizId) .get(); for (final doc in historySnapshot.docs) { await doc.reference.delete(); } } else { // Aluno: remover quiz criado ou conceito dominado if (type == 'created') { // Remover quiz criado pelo aluno final user = AuthService.currentUser; if (user != null) { await FirebaseFirestore.instance .collection('quizHistory') .doc(user.uid) .collection('quizzes') .doc(quizId) .delete(); } } else { // Remover conceito dominado final user = AuthService.currentUser; if (user != null) { final userStatsDoc = await FirebaseFirestore.instance .collection('userStats') .doc(user.uid) .get(); if (userStatsDoc.exists) { final userStats = userStatsDoc.data() as Map; final masteredConcepts = (userStats['masteredConcepts'] as List?) ?.map((c) => Map.from(c as Map)) .toList() ?? []; // Encontrar o conceito específico para remover final conceptToRemove = masteredConcepts.firstWhere( (c) => c['conceptName'] == quizId, orElse: () => {}, ); if (conceptToRemove.isNotEmpty) { await FirebaseFirestore.instance .collection('userStats') .doc(user.uid) .update({ 'masteredConcepts': FieldValue.arrayRemove([ conceptToRemove, ]), }); } } } } } _loadQuizHistory(); // Recarregar lista if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(successMessage), backgroundColor: Colors.green, ), ); } } catch (e) { Logger.error('Error deleting quiz: $e'); if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('Erro ao eliminar: $e'), backgroundColor: Colors.red, ), ); } } } Future _showDeleteConfirmation(String quizTitle, String message) async { final result = await showDialog( context: context, builder: (context) => AlertDialog( title: Text( _userRole == 'teacher' ? 'Eliminar Quiz' : 'Confirmar Eliminação', ), content: Text(message), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(false), child: const Text('Cancelar'), ), ElevatedButton( onPressed: () => Navigator.of(context).pop(true), style: ElevatedButton.styleFrom(backgroundColor: Colors.red), child: const Text('Eliminar'), ), ], ), ); return result ?? false; } Map>> _groupByClass() { final Map>> groups = {}; for (final quiz in _quizHistory) { final quizClassIds = (quiz['classIds'] as List?)?.cast() ?? []; String? groupId = quizClassIds.cast().firstWhere( (cid) => cid != null && _classNames.containsKey(cid), orElse: () => null, ); groupId ??= quizClassIds.isNotEmpty ? quizClassIds.first : '__geral__'; groups.putIfAbsent(groupId, () => []).add(quiz); } return groups; } List> _getFilteredQuizzes() { final searchQuery = _searchController.text.toLowerCase(); return _quizHistory.where((quiz) { // Filter by date if selected if (_selectedDate != null) { final quizDate = quiz['createdAt'] as Timestamp?; if (quizDate == null) return false; final quizDateTime = quizDate.toDate(); if (quizDateTime.year != _selectedDate!.year || quizDateTime.month != _selectedDate!.month || quizDateTime.day != _selectedDate!.day) { return false; } } // Filter by search query (class name or quiz title) if (searchQuery.isNotEmpty) { final title = (quiz['title'] as String? ?? '').toLowerCase(); final quizClassIds = (quiz['classIds'] as List?)?.cast() ?? []; bool matchesSearch = title.contains(searchQuery); for (final classId in quizClassIds) { if (_classNames.containsKey(classId)) { final className = _classNames[classId]!.toLowerCase(); if (className.contains(searchQuery)) { matchesSearch = true; break; } } } if (!matchesSearch) return false; } return true; }).toList(); } Map>> _getFilteredGroups() { final filteredQuizzes = _getFilteredQuizzes(); final Map>> groups = {}; for (final quiz in filteredQuizzes) { final quizClassIds = (quiz['classIds'] as List?)?.cast() ?? []; String? groupId = quizClassIds.cast().firstWhere( (cid) => cid != null && _classNames.containsKey(cid), orElse: () => null, ); groupId ??= quizClassIds.isNotEmpty ? quizClassIds.first : '__geral__'; groups.putIfAbsent(groupId, () => []).add(quiz); } return groups; } @override Widget build(BuildContext context) { final cs = Theme.of(context).colorScheme; return PopScope( canPop: _selectedClassId == null, onPopInvokedWithResult: (didPop, _) { if (!didPop && _selectedClassId != null) { setState(() => _selectedClassId = null); } }, child: Scaffold( backgroundColor: cs.surface, appBar: AppBar( title: Text( _userRole == 'teacher' ? 'Gerenciar Quizzes' : 'Meu Histórico', ), backgroundColor: cs.surface, foregroundColor: cs.onSurface, elevation: 0, leading: IconButton( icon: const Icon(Icons.arrow_back), onPressed: () { if (_userRole == 'teacher' && _selectedClassId != null) { setState(() => _selectedClassId = null); return; } if (Navigator.of(context).canPop()) { Navigator.of(context).pop(); } else { context.go( _userRole == 'teacher' ? '/teacher-dashboard' : '/student-dashboard', ); } }, ), actions: [ IconButton( icon: const Icon(Icons.calendar_today), onPressed: _selectDate, tooltip: 'Filtrar por data', ), if (_selectedDate != null) IconButton( icon: const Icon(Icons.clear), onPressed: () { setState(() => _selectedDate = null); }, tooltip: 'Limpar filtro', ), ], bottom: _selectedClassId == null ? PreferredSize( preferredSize: const Size.fromHeight(60), child: Padding( padding: const EdgeInsets.all(8), child: TextField( controller: _searchController, decoration: InputDecoration( hintText: 'Pesquisar turma...', prefixIcon: const Icon(Icons.search), border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), ), contentPadding: const EdgeInsets.symmetric( horizontal: 16, vertical: 12, ), ), onChanged: (value) => setState(() {}), ), ), ) : null, ), body: Container( decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [cs.primary.withValues(alpha: 0.05), cs.surface], ), ), child: _loading ? const Center(child: CircularProgressIndicator()) : _getFilteredQuizzes().isEmpty ? _buildEmptyState() : _userRole == 'teacher' ? _buildTeacherBody(cs) : ListView.builder( padding: const EdgeInsets.all(16), itemCount: _getFilteredQuizzes().length, itemBuilder: (context, index) { final quiz = _getFilteredQuizzes()[index]; return _buildQuizCard(quiz) .animate() .slideX(duration: const Duration(milliseconds: 300)) .then(delay: Duration(milliseconds: index * 50)); }, ), ), ), ); } Widget _buildTeacherBody(ColorScheme cs) { final groups = _searchController.text.isNotEmpty || _selectedDate != null ? _getFilteredGroups() : _groupByClass(); // Vista de quizzes de uma turma if (_selectedClassId != null) { final quizzes = groups[_selectedClassId] ?? []; final className = _classNames[_selectedClassId] ?? (_selectedClassId == '__geral__' ? 'Geral' : _selectedClassId!); return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: const EdgeInsets.fromLTRB(8, 8, 16, 0), child: Row( children: [ IconButton( icon: Icon(Icons.arrow_back, color: cs.onSurface), onPressed: () => setState(() => _selectedClassId = null), ), const SizedBox(width: 4), Expanded( child: Text( className, maxLines: 1, overflow: TextOverflow.ellipsis, style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, color: cs.onSurface, ), ), ), Text( '${quizzes.length} quiz${quizzes.length != 1 ? 'zes' : ''}', style: TextStyle(fontSize: 13, color: cs.onSurfaceVariant), ), ], ), ), const Divider(height: 1), Expanded( child: ListView.builder( padding: const EdgeInsets.all(16), itemCount: quizzes.length, itemBuilder: (context, index) { final quiz = quizzes[index]; return _buildQuizCard(quiz) .animate() .slideX(duration: const Duration(milliseconds: 300)) .then(delay: Duration(milliseconds: index * 50)); }, ), ), ], ); } // Vista de turmas final classIds = groups.keys.toList(); return ListView.separated( padding: const EdgeInsets.all(16), itemCount: classIds.length, separatorBuilder: (_, __) => const SizedBox(height: 12), itemBuilder: (context, i) { final cId = classIds[i]; final cName = _classNames[cId] ?? (cId == '__geral__' ? 'Geral' : cId); final count = groups[cId]!.length; return InkWell( borderRadius: BorderRadius.circular(16), onTap: () => setState(() => _selectedClassId = cId), child: Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( color: cs.surface, borderRadius: BorderRadius.circular(16), border: Border.all(color: cs.outline.withValues(alpha: 0.15)), boxShadow: [ BoxShadow( color: cs.shadow.withValues(alpha: 0.05), blurRadius: 8, offset: const Offset(0, 2), ), ], ), child: Row( children: [ Container( width: 48, height: 48, decoration: BoxDecoration( color: cs.primary.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(12), ), child: Icon(Icons.school, color: cs.primary, size: 26), ), const SizedBox(width: 16), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( cName, maxLines: 2, overflow: TextOverflow.ellipsis, style: TextStyle( fontSize: 15, fontWeight: FontWeight.bold, color: cs.onSurface, ), ), const SizedBox(height: 4), Text( '$count quiz${count != 1 ? 'zes' : ''} criado${count != 1 ? 's' : ''}', style: TextStyle( fontSize: 13, color: cs.onSurfaceVariant, ), ), ], ), ), Icon(Icons.chevron_right, color: cs.onSurfaceVariant), ], ), ), ); }, ); } Widget _buildEmptyState() { final cs = Theme.of(context).colorScheme; return Center( child: Padding( padding: const EdgeInsets.all(32), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( _userRole == 'teacher' ? Icons.quiz_outlined : Icons.history_edu_outlined, size: 64, color: cs.onSurfaceVariant, ), const SizedBox(height: 16), Text( _userRole == 'teacher' ? 'Nenhum quiz criado' : 'Nenhum quiz no histórico', style: TextStyle( color: cs.onSurface, fontSize: 20, fontWeight: FontWeight.bold, ), textAlign: TextAlign.center, ), const SizedBox(height: 8), Text( _userRole == 'teacher' ? 'Crie seu primeiro quiz para começar!' : 'Complete alguns quizzes para ver seu histórico aqui.', style: TextStyle(color: cs.onSurfaceVariant, fontSize: 14), textAlign: TextAlign.center, ), ], ), ), ); } Widget _buildQuizCard(Map quiz) { final cs = Theme.of(context).colorScheme; return Container( margin: const EdgeInsets.only(bottom: 12), padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: cs.surface, borderRadius: BorderRadius.circular(16), border: Border.all(color: cs.outline.withValues(alpha: 0.2)), boxShadow: [ BoxShadow( color: cs.shadow.withValues(alpha: 0.1), blurRadius: 10, offset: const Offset(0, 4), ), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( quiz['title'] ?? 'Quiz sem título', style: TextStyle( color: cs.onSurface, fontSize: 16, fontWeight: FontWeight.bold, ), ), const SizedBox(height: 4), if (_userRole == 'student' && quiz['score'] != null) ...[ Text( 'Pontuação: ${quiz['score']}/${quiz['totalQuestions'] ?? '?'}', style: TextStyle( color: cs.primary, fontSize: 14, fontWeight: FontWeight.w500, ), ), ], Text( _userRole == 'teacher' || quiz['type'] == 'created' ? 'Criado em: ${_formatDate(quiz['createdAt'])}' : 'Completado em: ${_formatDate(quiz['completedAt'])}', style: TextStyle( color: cs.onSurfaceVariant, fontSize: 12, ), ), ], ), ), IconButton( onPressed: () => _deleteQuiz( quiz['id'], quiz['title'] ?? 'Quiz', quiz['type'] ?? 'unknown', ), icon: Icon(Icons.delete_outline, color: Colors.red), tooltip: _userRole == 'teacher' ? 'Eliminar Quiz' : 'Remover', ), ], ), if (_userRole == 'teacher' && quiz['classIds'] != null && _selectedClassId == null) ...[ const SizedBox(height: 8), Wrap( spacing: 4, children: (quiz['classIds'] as List).map((classId) { return Container( padding: const EdgeInsets.symmetric( horizontal: 8, vertical: 4, ), decoration: BoxDecoration( color: cs.primaryContainer, borderRadius: BorderRadius.circular(8), ), child: Text( 'Disciplina: $classId', style: TextStyle( color: cs.onPrimaryContainer, fontSize: 10, ), ), ); }).toList(), ), ], ], ), ); } String _formatDate(dynamic date) { if (date == null) return 'Data desconhecida'; DateTime dateTime; if (date is Timestamp) { dateTime = date.toDate(); } else if (date is DateTime) { dateTime = date; } else { return 'Data desconhecida'; } return '${dateTime.day}/${dateTime.month}/${dateTime.year}'; } }