import 'package:flutter/material.dart'; import 'package:mobile_scanner/mobile_scanner.dart'; import 'package:provider/provider.dart'; import 'package:farolero/l10n/generated/app_localizations.dart'; import '../servicios/servicio_nearby.dart'; import '../tema/tema_app.dart'; /// Pantalla para unirse a una partida multidispositivo class PantallaUnirse extends StatefulWidget { const PantallaUnirse({super.key}); @override State createState() => _PantallaUnirseState(); } class _PantallaUnirseState extends State { final _nombreController = TextEditingController(); final _formKey = GlobalKey(); bool _escaneando = false; bool _conectando = false; String? _error; String? _salaEncontrada; @override void dispose() { _nombreController.dispose(); super.dispose(); } Future _iniciarEscaneo() async { if (!_formKey.currentState!.validate()) return; setState(() { _escaneando = true; _error = null; }); } Future _onQRDetectado(BarcodeCapture capture) async { if (_conectando) return; for (final barcode in capture.barcodes) { final valor = barcode.rawValue; if (valor == null) continue; final datos = ServicioNearby.parsearQR(valor); if (datos != null) { setState(() { _escaneando = false; _conectando = true; _salaEncontrada = datos['sala'] as String? ?? 'Sala'; }); // Iniciar búsqueda de hosts via Nearby final nearby = context.read(); final ok = await nearby.buscarHosts(_nombreController.text.trim()); if (!ok && mounted) { setState(() { _conectando = false; _error = 'No se pudo iniciar la búsqueda. Verifica Bluetooth y ubicación.'; }); } return; } } } @override Widget build(BuildContext context) { final l10n = AppLocalizations.of(context)!; final nearby = context.watch(); // Si estamos conectados, mostrar pantalla de espera if (nearby.conectado && !nearby.esHost) { return _buildPantallaEspera(context, l10n, nearby); } return Scaffold( appBar: AppBar( title: Text(l10n.joinGameTitle), leading: IconButton( icon: const Icon(Icons.close), onPressed: () async { await nearby.desconectar(); if (context.mounted) Navigator.pop(context); }, ), ), body: _escaneando ? _buildEscaner(context, l10n) : _buildFormulario(context, l10n), ); } Widget _buildFormulario(BuildContext context, AppLocalizations l10n) { return Padding( padding: const EdgeInsets.all(32), child: Form( key: _formKey, child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const Text('📱', style: TextStyle(fontSize: 64)), const SizedBox(height: 24), Text( l10n.joinGameTitle, style: Theme.of(context).textTheme.headlineMedium, ), const SizedBox(height: 8), Text( l10n.enterNameAndScan, style: Theme.of(context).textTheme.bodyLarge, textAlign: TextAlign.center, ), const SizedBox(height: 32), // Campo nombre TextFormField( controller: _nombreController, decoration: InputDecoration( labelText: l10n.yourName, prefixIcon: const Icon(Icons.person), ), validator: (v) { if (v == null || v.trim().isEmpty) { return l10n.nameRequired; } return null; }, textCapitalization: TextCapitalization.words, ), const SizedBox(height: 24), if (_conectando) ...[ const CircularProgressIndicator(color: TemaApp.colorAcento), const SizedBox(height: 12), Text( '${l10n.connectingTo} ${_salaEncontrada ?? ""}...', style: Theme.of(context).textTheme.bodyMedium, ), ] else ...[ // Botón escanear QR SizedBox( width: double.infinity, child: ElevatedButton.icon( onPressed: _iniciarEscaneo, icon: const Icon(Icons.qr_code_scanner), label: Text(l10n.scanQR), ), ), ], if (_error != null) ...[ const SizedBox(height: 16), Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: TemaApp.colorAcento.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(12), ), child: Text( _error!, style: const TextStyle(color: TemaApp.colorAcento), textAlign: TextAlign.center, ), ), ], ], ), ), ); } Widget _buildEscaner(BuildContext context, AppLocalizations l10n) { return Stack( children: [ MobileScanner( onDetect: _onQRDetectado, ), // Overlay Positioned( bottom: 0, left: 0, right: 0, child: Container( padding: const EdgeInsets.all(24), decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ Colors.transparent, Colors.black.withValues(alpha: 0.8), ], ), ), child: Column( mainAxisSize: MainAxisSize.min, children: [ Text( l10n.scanHostQR, style: Theme.of(context).textTheme.titleLarge?.copyWith( color: Colors.white, ), ), const SizedBox(height: 16), OutlinedButton( onPressed: () => setState(() => _escaneando = false), style: OutlinedButton.styleFrom( foregroundColor: Colors.white, side: const BorderSide(color: Colors.white), ), child: Text(l10n.cancel), ), ], ), ), ), ], ); } Widget _buildPantallaEspera( BuildContext context, AppLocalizations l10n, ServicioNearby nearby, ) { return Scaffold( appBar: AppBar( title: Text(_salaEncontrada ?? l10n.joinGameTitle), leading: IconButton( icon: const Icon(Icons.close), onPressed: () async { await nearby.desconectar(); if (context.mounted) Navigator.pop(context); }, ), ), body: Center( child: Padding( padding: const EdgeInsets.all(32), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const Text('✅', style: TextStyle(fontSize: 64)), const SizedBox(height: 24), Text( l10n.connectedWaiting, style: Theme.of(context).textTheme.headlineMedium, textAlign: TextAlign.center, ), const SizedBox(height: 12), Text( '${l10n.yourName}: ${_nombreController.text}', style: Theme.of(context).textTheme.bodyLarge, ), const SizedBox(height: 32), const CircularProgressIndicator(color: TemaApp.colorNaranja), const SizedBox(height: 16), Text( l10n.waitingForHost, style: Theme.of(context).textTheme.bodyMedium, ), ], ), ), ), ); } }