import 'package:flutter/material.dart'; import 'package:supabase_flutter/supabase_flutter.dart'; import '../controllers/team_controller.dart'; import '../utils/size_extension.dart'; import 'dart:math' as math; import '../controllers/placar_controller.dart'; // Para a classe ShotRecord import '../pages/heatmap_page.dart'; // Para abrir a página do mapa class StatusPage extends StatefulWidget { const StatusPage({super.key}); @override State createState() => _StatusPageState(); } class _StatusPageState extends State { final TeamController _teamController = TeamController(); final _supabase = Supabase.instance.client; String? _selectedTeamId; String _selectedTeamName = "Selecionar Equipa"; String _sortColumn = 'pts'; bool _isAscending = false; // 👇 NOVA FUNÇÃO: BUSCA OS LANÇAMENTOS DO JOGADOR NO SUPABASE E ABRE O MAPA Future _openPlayerHeatmap(String playerName) async { if (_selectedTeamId == null) return; // Mostra um loading rápido showDialog( context: context, barrierDismissible: false, builder: (_) => const Center(child: CircularProgressIndicator(color: Color(0xFFE74C3C))) ); try { final response = await _supabase .from('game_shots') .select() .eq('team_id', _selectedTeamId!) .eq('player_name', playerName); if (mounted) Navigator.pop(context); // Fecha o loading if (response == null || (response as List).isEmpty) { if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('O $playerName ainda não tem lançamentos registados!')) ); } return; } final List shots = (response as List).map((s) => ShotRecord( relativeX: (s['relative_x'] as num).toDouble(), relativeY: (s['relative_y'] as num).toDouble(), isMake: s['is_make'] as bool, playerName: s['player_name'], )).toList(); if (mounted) { Navigator.push(context, MaterialPageRoute( builder: (_) => HeatmapPage(shots: shots, teamName: "Mapa de: $playerName") )); } } catch (e) { if (mounted) Navigator.pop(context); debugPrint("Erro ao carregar heatmap: $e"); } } @override Widget build(BuildContext context) { final double safeSf = math.min(context.sf, 1.15); final double screenWidth = MediaQuery.of(context).size.width; return Column( children: [ // --- SELETOR DE EQUIPA --- Padding( padding: EdgeInsets.all(16.0 * safeSf), child: InkWell( onTap: () => _showTeamSelector(context, safeSf), child: Container( padding: EdgeInsets.all(12 * safeSf), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(15 * safeSf), border: Border.all(color: Colors.grey.shade300), boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 5)] ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Row(children: [ Icon(Icons.shield, color: const Color(0xFFE74C3C), size: 24 * safeSf), SizedBox(width: 10 * safeSf), Text(_selectedTeamName, style: TextStyle(fontSize: 16 * safeSf, fontWeight: FontWeight.bold)) ]), const Icon(Icons.arrow_drop_down), ], ), ), ), ), // --- TABELA DE ESTATÍSTICAS --- Expanded( child: _selectedTeamId == null ? Center(child: Text("Seleciona uma equipa acima.", style: TextStyle(color: Colors.grey, fontSize: 14 * safeSf))) : StreamBuilder>>( stream: _supabase.from('player_stats_with_names').stream(primaryKey: ['id']).eq('team_id', _selectedTeamId!), builder: (context, statsSnapshot) { return StreamBuilder>>( stream: _supabase.from('games').stream(primaryKey: ['id']).eq('my_team', _selectedTeamName), builder: (context, gamesSnapshot) { return StreamBuilder>>( stream: _supabase.from('members').stream(primaryKey: ['id']).eq('team_id', _selectedTeamId!), builder: (context, membersSnapshot) { if (statsSnapshot.connectionState == ConnectionState.waiting || gamesSnapshot.connectionState == ConnectionState.waiting || membersSnapshot.connectionState == ConnectionState.waiting) { return const Center(child: CircularProgressIndicator(color: Color(0xFFE74C3C))); } final membersData = membersSnapshot.data ?? []; if (membersData.isEmpty) return Center(child: Text("Esta equipa não tem jogadores registados.", style: TextStyle(color: Colors.grey, fontSize: 14 * safeSf))); final statsData = statsSnapshot.data ?? []; final gamesData = gamesSnapshot.data ?? []; final totalGamesPlayedByTeam = gamesData.where((g) => g['status'] == 'Terminado').length; final List> playerTotals = _aggregateStats(statsData, gamesData, membersData); final teamTotals = _calculateTeamTotals(playerTotals, totalGamesPlayedByTeam); playerTotals.sort((a, b) { var valA = a[_sortColumn] ?? 0; var valB = b[_sortColumn] ?? 0; return _isAscending ? valA.compareTo(valB) : valB.compareTo(valA); }); return _buildStatsGrid(context, playerTotals, teamTotals, safeSf, screenWidth); } ); } ); } ), ), ], ); } // (Lógica de _aggregateStats e _calculateTeamTotals continua igual...) List> _aggregateStats(List stats, List games, List members) { Map> aggregated = {}; for (var member in members) { String name = member['name']?.toString() ?? "Desconhecido"; aggregated[name] = {'name': name, 'j': 0, 'pts': 0, 'ast': 0, 'rbs': 0, 'stl': 0, 'blk': 0, 'mvp': 0, 'def': 0}; } for (var row in stats) { String name = row['player_name']?.toString() ?? "Desconhecido"; if (!aggregated.containsKey(name)) aggregated[name] = {'name': name, 'j': 0, 'pts': 0, 'ast': 0, 'rbs': 0, 'stl': 0, 'blk': 0, 'mvp': 0, 'def': 0}; aggregated[name]!['j'] += 1; aggregated[name]!['pts'] += (row['pts'] ?? 0); aggregated[name]!['ast'] += (row['ast'] ?? 0); aggregated[name]!['rbs'] += (row['rbs'] ?? 0); aggregated[name]!['stl'] += (row['stl'] ?? 0); aggregated[name]!['blk'] += (row['blk'] ?? 0); } for (var game in games) { String? mvp = game['mvp_name']; String? defRaw = game['top_def_name']; if (mvp != null && aggregated.containsKey(mvp)) aggregated[mvp]!['mvp'] += 1; if (defRaw != null) { String defName = defRaw.split(' (')[0].trim(); if (aggregated.containsKey(defName)) aggregated[defName]!['def'] += 1; } } return aggregated.values.toList(); } Map _calculateTeamTotals(List> players, int teamGames) { int tPts = 0, tAst = 0, tRbs = 0, tStl = 0, tBlk = 0, tMvp = 0, tDef = 0; for (var p in players) { tPts += (p['pts'] as int); tAst += (p['ast'] as int); tRbs += (p['rbs'] as int); tStl += (p['stl'] as int); tBlk += (p['blk'] as int); tMvp += (p['mvp'] as int); tDef += (p['def'] as int); } return {'name': 'TOTAL EQUIPA', 'j': teamGames, 'pts': tPts, 'ast': tAst, 'rbs': tRbs, 'stl': tStl, 'blk': tBlk, 'mvp': tMvp, 'def': tDef}; } Widget _buildStatsGrid(BuildContext context, List> players, Map teamTotals, double safeSf, double screenWidth) { double dynamicSpacing = math.max(15 * safeSf, (screenWidth - (180 * safeSf)) / 8); return Container( color: Colors.white, width: double.infinity, child: SingleChildScrollView( scrollDirection: Axis.vertical, child: SingleChildScrollView( scrollDirection: Axis.horizontal, child: ConstrainedBox( constraints: BoxConstraints(minWidth: screenWidth), child: DataTable( columnSpacing: dynamicSpacing, horizontalMargin: 20 * safeSf, headingRowColor: MaterialStateProperty.all(Colors.grey.shade100), dataRowHeight: 60 * safeSf, columns: [ DataColumn(label: const Text('JOGADOR')), _buildSortableColumn('J', 'j', safeSf), _buildSortableColumn('PTS', 'pts', safeSf), _buildSortableColumn('AST', 'ast', safeSf), _buildSortableColumn('RBS', 'rbs', safeSf), _buildSortableColumn('STL', 'stl', safeSf), _buildSortableColumn('BLK', 'blk', safeSf), _buildSortableColumn('DEF 🛡️', 'def', safeSf), _buildSortableColumn('MVP 🏆', 'mvp', safeSf), ], rows: [ ...players.map((player) => DataRow(cells: [ DataCell( // 👇 TORNEI O NOME CLICÁVEL PARA ABRIR O MAPA InkWell( onTap: () => _openPlayerHeatmap(player['name']), child: Row(children: [ CircleAvatar(radius: 15 * safeSf, backgroundColor: Colors.grey.shade200, child: Icon(Icons.person, size: 18 * safeSf)), SizedBox(width: 10 * safeSf), Text(player['name'], style: TextStyle(fontWeight: FontWeight.bold, fontSize: 13 * safeSf, color: Colors.blue.shade700)) ]), ) ), DataCell(Center(child: Text(player['j'].toString()))), _buildStatCell(player['pts'], safeSf, isHighlight: true), _buildStatCell(player['ast'], safeSf), _buildStatCell(player['rbs'], safeSf), _buildStatCell(player['stl'], safeSf), _buildStatCell(player['blk'], safeSf), _buildStatCell(player['def'], safeSf, isBlue: true), _buildStatCell(player['mvp'], safeSf, isGold: true), ])), DataRow( color: MaterialStateProperty.all(Colors.grey.shade50), cells: [ DataCell(Text('TOTAL EQUIPA', style: TextStyle(fontWeight: FontWeight.w900, color: Colors.black, fontSize: 12 * safeSf))), DataCell(Center(child: Text(teamTotals['j'].toString(), style: const TextStyle(fontWeight: FontWeight.bold)))), _buildStatCell(teamTotals['pts'], safeSf, isHighlight: true), _buildStatCell(teamTotals['ast'], safeSf), _buildStatCell(teamTotals['rbs'], safeSf), _buildStatCell(teamTotals['stl'], safeSf), _buildStatCell(teamTotals['blk'], safeSf), _buildStatCell(teamTotals['def'], safeSf, isBlue: true), _buildStatCell(teamTotals['mvp'], safeSf, isGold: true), ] ) ], ), ), ), ), ); } // (Outras funções de build continuam igual...) DataColumn _buildSortableColumn(String title, String sortKey, double safeSf) { return DataColumn(label: InkWell( onTap: () => setState(() { if (_sortColumn == sortKey) _isAscending = !_isAscending; else { _sortColumn = sortKey; _isAscending = false; } }), child: Row( mainAxisSize: MainAxisSize.min, children: [ Text(title, style: TextStyle(fontSize: 12 * safeSf, fontWeight: FontWeight.bold)), if (_sortColumn == sortKey) Icon(_isAscending ? Icons.arrow_drop_up : Icons.arrow_drop_down, size: 18 * safeSf, color: const Color(0xFFE74C3C)), ] ), )); } DataCell _buildStatCell(int value, double safeSf, {bool isHighlight = false, bool isGold = false, bool isBlue = false}) { return DataCell(Center(child: Container( padding: EdgeInsets.symmetric(horizontal: 8 * safeSf, vertical: 4 * safeSf), decoration: BoxDecoration(color: isGold && value > 0 ? Colors.amber.withOpacity(0.2) : (isBlue && value > 0 ? Colors.blue.withOpacity(0.1) : Colors.transparent), borderRadius: BorderRadius.circular(6)), child: Text(value == 0 ? "-" : value.toString(), style: TextStyle( fontWeight: (isHighlight || isGold || isBlue) ? FontWeight.w900 : FontWeight.w600, fontSize: 14 * safeSf, color: isGold && value > 0 ? Colors.orange.shade900 : (isBlue && value > 0 ? Colors.blue.shade800 : (isHighlight ? Colors.green.shade700 : Colors.black87)) )), ))); } void _showTeamSelector(BuildContext context, double safeSf) { showModalBottomSheet(context: context, builder: (context) => StreamBuilder>>( stream: _teamController.teamsStream, builder: (context, snapshot) { final teams = snapshot.data ?? []; return ListView.builder(itemCount: teams.length, itemBuilder: (context, i) => ListTile( title: Text(teams[i]['name'], style: TextStyle(fontSize: 15 * safeSf)), onTap: () { setState(() { _selectedTeamId = teams[i]['id']; _selectedTeamName = teams[i]['name']; }); Navigator.pop(context); }, )); }, )); } }