import 'package:farolero/l10n/generated/app_localizations.dart'; import 'package:flutter/material.dart'; import 'package:flutter_animate/flutter_animate.dart'; import 'package:provider/provider.dart'; import '../modelos/inicio_partida_multijugador.dart'; import '../modelos/gamificacion_usuario.dart'; import '../modelos/palabra.dart'; import '../modelos/snapshot_partida_online.dart'; import '../servicios/servicio_historial_partidas.dart'; import '../servicios/servicio_nearby.dart'; import '../servicios/servicio_perfil_usuario.dart'; import '../tema/componentes_farolero.dart'; import '../tema/tema_app.dart'; import 'pantalla_notas_online.dart'; import 'pantalla_principal.dart'; import 'pantalla_revision_palabra.dart'; class PantallaFinPartidaOnline extends StatefulWidget { final SnapshotPartidaOnline snapshot; final List jugadoresControlados; final String? pistaCategoria; const PantallaFinPartidaOnline({ super.key, required this.snapshot, required this.jugadoresControlados, this.pistaCategoria, }); @override State createState() => _PantallaFinPartidaOnlineState(); } class _PantallaFinPartidaOnlineState extends State { bool _guardada = false; ProgresoGamificacionUsuario? _progreso; @override Widget build(BuildContext context) { final l10n = AppLocalizations.of(context)!; final snapshot = widget.snapshot; final jugadoresControlados = widget.jugadoresControlados; final pistaCategoria = widget.pistaCategoria; final ganaronJugadores = snapshot.ganador == 'jugadores'; if (!_guardada && snapshot.ganador != null) { _guardada = true; WidgetsBinding.instance.addPostFrameCallback((_) async { if (mounted) { final historial = context.read(); final perfil = context.read(); await historial.guardarSnapshotOnline(snapshot); final progreso = await perfil.registrarPartidaCompletada( victoria: _perfilLocalGano(snapshot, jugadoresControlados), comoImpostor: jugadoresControlados.any((j) => j.esImpostor), victoriaComoImpostor: snapshot.ganador == 'impostores' && jugadoresControlados.any((j) => j.esImpostor), ); if (mounted) setState(() => _progreso = progreso); } }); } return Scaffold( appBar: AppBar( title: Text(l10n.gameOver), automaticallyImplyLeading: false, actions: [ IconButton( tooltip: l10n.seeYourWord, icon: const Icon(Icons.visibility), onPressed: jugadoresControlados.isEmpty ? null : () => mostrarRevisionPalabraOnline( context: context, jugadoresControlados: jugadoresControlados, pistaCategoria: pistaCategoria, ), ), IconButton( tooltip: l10n.notesTitle, icon: const Icon(Icons.edit_note), onPressed: snapshot.roomId == null || jugadoresControlados.isEmpty ? null : () => Navigator.push( context, MaterialPageRoute( builder: (_) => PantallaNotasOnline( partidaId: snapshot.roomId!, jugadores: snapshot.jugadores, autoresControlados: jugadoresControlados, ), ), ), ), ], ), body: FondoFarolero( intenso: true, child: SingleChildScrollView( padding: const EdgeInsets.all(24), child: Column( children: [ _ResultadoOnlineHero( ganaronJugadores: ganaronJugadores, titulo: ganaronJugadores ? l10n.playersWin : l10n.impostorsWin, ), const SizedBox(height: 24), if (_progreso != null) ...[ _TarjetaProgresoGamificacion(progreso: _progreso!), const SizedBox(height: 16), ], Card( child: Padding( padding: const EdgeInsets.all(20), child: Column( children: [ Text( l10n.theSecretWordWas, style: Theme.of(context).textTheme.titleMedium, ), const SizedBox(height: 8), Text( snapshot.palabraSecreta ?? '?', style: Theme.of(context).textTheme.headlineLarge?.copyWith( color: TemaApp.colorNaranja, fontSize: 32, ), ), const SizedBox(height: 4), Text( l10n.categoryLabel( BancoPalabras.nombreBonitoCategoria( snapshot.categoria, l10n, ), ), style: Theme.of(context).textTheme.bodyMedium, ), ], ), ), ), const SizedBox(height: 16), Card( child: Padding( padding: const EdgeInsets.all(20), child: Column( children: [ Text( snapshot.impostores.length == 1 ? l10n.theImpostorWas : l10n.theImpostorsWere, style: Theme.of(context).textTheme.titleMedium, ), const SizedBox(height: 8), ...snapshot.impostores.map( (nombre) => Padding( padding: const EdgeInsets.symmetric(vertical: 4), child: Text( '🎭 $nombre', style: Theme.of(context).textTheme.titleLarge?.copyWith( color: TemaApp.colorAcento, ), ), ), ), ], ), ), ), const SizedBox(height: 16), if (snapshot.historialVotaciones.isNotEmpty) Card( child: Padding( padding: const EdgeInsets.all(20), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( l10n.votingHistory, style: Theme.of(context).textTheme.titleMedium, ), const SizedBox(height: 12), ...snapshot.historialVotaciones.asMap().entries.map( (entrada) { final ronda = entrada.key + 1; final resultado = entrada.value; return Padding( padding: const EdgeInsets.only(bottom: 12), child: Text( l10n.roundElimination( ronda, resultado.eliminadoNombre, ), style: TextStyle( fontWeight: FontWeight.bold, color: resultado.eraImpostor ? TemaApp.colorVerde : TemaApp.colorAcento, ), ), ); }, ), ], ), ), ), const SizedBox(height: 24), SizedBox( width: double.infinity, height: 56, child: OutlinedButton.icon( onPressed: () async { await context.read().desconectar(); if (!context.mounted) return; Navigator.pushAndRemoveUntil( context, MaterialPageRoute( builder: (_) => const PantallaPrincipal(), ), (route) => false, ); }, icon: const Icon(Icons.home), label: Text(l10n.mainMenu), ), ), ], ), ), ), ); } bool _perfilLocalGano( SnapshotPartidaOnline snapshot, List jugadoresControlados, ) { if (jugadoresControlados.isEmpty) return snapshot.ganador == 'jugadores'; final ganaronImpostores = snapshot.ganador == 'impostores'; return jugadoresControlados.any( (jugador) => jugador.esImpostor ? ganaronImpostores : !ganaronImpostores, ); } } class _ResultadoOnlineHero extends StatelessWidget { final bool ganaronJugadores; final String titulo; const _ResultadoOnlineHero({ required this.ganaronJugadores, required this.titulo, }); @override Widget build(BuildContext context) { final color = ganaronJugadores ? TemaApp.colorVerde : TemaApp.colorAcento; return Container( width: double.infinity, padding: const EdgeInsets.fromLTRB(20, 18, 20, 24), decoration: BoxDecoration( gradient: LinearGradient( colors: [ color.withValues(alpha: 0.20), const Color(0xFF101827).withValues(alpha: 0.68), ], begin: Alignment.topCenter, end: Alignment.bottomCenter, ), borderRadius: BorderRadius.circular(28), border: Border.all(color: color.withValues(alpha: 0.65)), ), child: Column( children: [ Image.asset( 'assets/ui/generated/final_rewards/cinematic_burst.png', height: 250, fit: BoxFit.contain, opacity: const AlwaysStoppedAnimation(0.95), ), const SizedBox(height: 8), Text( titulo, style: Theme.of(context).textTheme.headlineMedium?.copyWith( color: color, fontWeight: FontWeight.w900, shadows: [ Shadow(color: color.withValues(alpha: 0.75), blurRadius: 18), ], ), textAlign: TextAlign.center, ), ], ), ).animate().fadeIn(duration: 320.ms).slideY(begin: -0.08); } } class _TarjetaProgresoGamificacion extends StatelessWidget { final ProgresoGamificacionUsuario progreso; const _TarjetaProgresoGamificacion({required this.progreso}); @override Widget build(BuildContext context) { final nuevas = progreso.nuevasMedallas; return Container( width: double.infinity, padding: const EdgeInsets.all(18), decoration: BoxDecoration( gradient: LinearGradient( colors: [ const Color(0xFF111B28).withValues(alpha: 0.96), const Color(0xFF180D22).withValues(alpha: 0.94), ], begin: Alignment.topLeft, end: Alignment.bottomRight, ), borderRadius: BorderRadius.circular(22), border: Border.all(color: TemaApp.colorDorado.withValues(alpha: 0.52)), boxShadow: [ BoxShadow( color: TemaApp.colorNaranja.withValues(alpha: 0.18), blurRadius: 32, offset: const Offset(0, 16), ), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ const Icon(Icons.local_fire_department, color: TemaApp.colorNaranja), const SizedBox(width: 8), Expanded( child: Text( 'RECOMPENSAS DE PARTIDA', style: Theme.of(context).textTheme.titleMedium?.copyWith( color: TemaApp.colorDorado, fontWeight: FontWeight.w900, letterSpacing: 1, ), ), ), Text( progreso.incrementoFuego >= 0 ? '+${progreso.incrementoFuego}' : '${progreso.incrementoFuego}', style: Theme.of(context).textTheme.titleMedium?.copyWith( color: TemaApp.colorDorado, fontWeight: FontWeight.w900, ), ), ], ), const SizedBox(height: 12), TweenAnimationBuilder( tween: Tween( begin: progreso.antes.fuego.clamp(0, 100) / 100, end: progreso.despues.fuego.clamp(0, 100) / 100, ), duration: const Duration(milliseconds: 1300), curve: Curves.easeOutCubic, builder: (context, value, _) => ClipRRect( borderRadius: BorderRadius.circular(999), child: LinearProgressIndicator( value: value.clamp(0.0, 1.0).toDouble(), minHeight: 18, backgroundColor: Colors.black.withValues(alpha: 0.35), valueColor: const AlwaysStoppedAnimation(TemaApp.colorNaranja), ), ), ), const SizedBox(height: 8), Text( '${progreso.despues.fuego}% de fuego', style: Theme.of(context).textTheme.bodySmall, ), if (nuevas.isNotEmpty) ...[ const SizedBox(height: 12), Text( 'NUEVAS MEDALLAS', style: Theme.of(context).textTheme.bodyMedium?.copyWith( color: TemaApp.colorDorado, fontWeight: FontWeight.w800, ), ), const SizedBox(height: 6), MedallasCompactasFarolero(ids: nuevas, max: nuevas.length), ], ], ), ) .animate() .fadeIn(duration: 360.ms) .slideY(begin: 0.12) .shimmer(delay: 700.ms, duration: 1200.ms); } }