import 'package:flutter/material.dart'; import 'package:dio/dio.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:flutter_map/flutter_map.dart'; import 'package:latlong2/latlong.dart'; import '../../core/theme/app_theme.dart'; import '../../core/models/ui_models.dart'; import 'colonias_data.dart'; class CitizenHomeScreen extends StatefulWidget { const CitizenHomeScreen({super.key}); @override State createState() => _CitizenHomeScreenState(); } class _CitizenHomeScreenState extends State { bool _isLoading = true; List _casas = []; Map _etas = {}; Map _horarios = {}; @override void initState() { super.initState(); _loadData(); } Future _loadData() async { try { const storage = FlutterSecureStorage(); final token = await storage.read(key: 'token') ?? ''; if (token.isEmpty) { if (mounted) setState(() => _isLoading = false); return; } final dio = Dio( BaseOptions( baseUrl: const String.fromEnvironment( 'API_BASE_URL', defaultValue: 'http://localhost:8000', ), headers: {'Authorization': 'Bearer $token'}, ), ); // 1. Obtener horarios de las colonias try { final colRes = await dio.get('/colonias'); if (colRes.data is List) { for (var c in colRes.data) { final nombre = c['nombre'] ?? c['colonia'] ?? ''; final horario = c['horario_estimado'] ?? c['schedule'] ?? 'Horario no definido'; if (nombre.isNotEmpty) { _horarios[nombre] = horario; } } } } catch (_) { debugPrint('Aviso: No se pudieron cargar los horarios.'); } // 2. Obtener los domicilios del ciudadano final res = await dio.get('/addresses'); List loadedCasas = []; if (res.data is List) { loadedCasas = (res.data as List).map((e) => UIHouseModel.fromJson(e)).toList(); } // 3. Obtener ETA (Tiempo Estimado) para cada domicilio Map loadedEtas = {}; for (var casa in loadedCasas) { try { final etaRes = await dio.get('/eta', queryParameters: {'address_id': casa.id}); loadedEtas[casa.id] = etaRes.data['mensaje'] ?? 'Estado desconocido'; } catch (e) { loadedEtas[casa.id] = 'Calculando...'; } } if (mounted) { setState(() { _casas = loadedCasas; _etas = loadedEtas; _isLoading = false; }); } } catch (e) { debugPrint('Error en CitizenHomeScreen: $e'); if (mounted) { setState(() => _isLoading = false); } } } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: AppTheme.background, appBar: AppBar( title: const Text('Estado del Servicio'), actions: [ IconButton( icon: const Icon(Icons.refresh), tooltip: 'Actualizar tiempos', onPressed: () { setState(() => _isLoading = true); _loadData(); }, ) ], ), body: _isLoading ? const Center(child: CircularProgressIndicator()) : _casas.isEmpty ? const Center( child: Text( 'No tienes domicilios registrados.', style: TextStyle(color: AppTheme.textSecondary), ), ) : ListView.separated( padding: const EdgeInsets.all(16), itemCount: _casas.length, separatorBuilder: (_, __) => const SizedBox(height: 24), itemBuilder: (context, index) { final casa = _casas[index]; final eta = _etas[casa.id] ?? 'Actualizando...'; final horario = _horarios[casa.colonia] ?? 'Horario asignado a la ruta'; return _HouseEtaCard(casa: casa, etaMsg: eta, horario: horario); }, ), ); } } // ── Widget para la Tarjeta de Mapa y ETA ───────────────────────────────────── class _HouseEtaCard extends StatelessWidget { final UIHouseModel casa; final String etaMsg; final String horario; const _HouseEtaCard({ required this.casa, required this.etaMsg, required this.horario, }); @override Widget build(BuildContext context) { final center = kColoniasCoordinates[casa.colonia] ?? const LatLng(20.5222, -100.8123); // Restricción del mapa a la colonia (Privacidad por Diseño) final bounds = LatLngBounds( LatLng(center.latitude - 0.01, center.longitude - 0.01), LatLng(center.latitude + 0.01, center.longitude + 0.01), ); return Container( decoration: BoxDecoration( color: AppTheme.surface, borderRadius: BorderRadius.circular(AppTheme.radiusLg), border: Border.all(color: AppTheme.border), boxShadow: AppTheme.cardShadow, ), clipBehavior: Clip.hardEdge, child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ // ── Mapa Restringido ── SizedBox( height: 180, child: FlutterMap( options: MapOptions( initialCameraFit: CameraFit.bounds(bounds: bounds), cameraConstraint: CameraConstraint.contain(bounds: bounds), interactionOptions: const InteractionOptions( flags: InteractiveFlag.drag | InteractiveFlag.pinchZoom, ), ), children: [ TileLayer( urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png', userAgentPackageName: 'com.onlineshack.recolecta', ), CircleLayer( circles: [ CircleMarker( point: center, color: AppTheme.primary.withValues(alpha: 0.15), borderColor: AppTheme.primary, borderStrokeWidth: 2, radius: 400, useRadiusInMeter: true, ), ], ), ], ), ), // ── Recuadro de Información ── Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ const Icon(Icons.home, color: AppTheme.primary, size: 20), const SizedBox(width: 8), Text( casa.alias.isNotEmpty ? casa.alias : 'Mi Domicilio', style: const TextStyle( fontSize: 16, fontWeight: FontWeight.w700, color: AppTheme.textPrimary, ), ), ], ), const SizedBox(height: 14), _InfoRow(icon: Icons.location_on_outlined, title: 'Dirección', value: casa.direccionCompleta), const SizedBox(height: 12), _InfoRow(icon: Icons.schedule_outlined, title: 'Horario Habitual', value: horario), const SizedBox(height: 18), // ── Alerta de ETA en Tiempo Real ── Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: AppTheme.primaryLight, borderRadius: BorderRadius.circular(AppTheme.radiusSm), border: Border.all(color: AppTheme.primaryMid), ), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Icon(Icons.local_shipping_outlined, color: AppTheme.primaryDark), const SizedBox(width: 10), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( 'Estado del Camión', style: TextStyle( fontSize: 12, fontWeight: FontWeight.w600, color: AppTheme.primaryDark, ), ), const SizedBox(height: 4), Text( etaMsg, style: const TextStyle( fontSize: 14, fontWeight: FontWeight.w500, color: AppTheme.primaryDark, ), ), ], ), ), ], ), ), ], ), ), ], ), ); } } // ── Fila auxiliar de info ──────────────────────────────────────────────────── class _InfoRow extends StatelessWidget { final IconData icon; final String title; final String value; const _InfoRow({required this.icon, required this.title, required this.value}); @override Widget build(BuildContext context) { return Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Icon(icon, size: 18, color: AppTheme.textSecondary), const SizedBox(width: 10), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( title, style: const TextStyle(fontSize: 12, color: AppTheme.textSecondary, fontWeight: FontWeight.w500), ), const SizedBox(height: 2), Text( value, style: const TextStyle(fontSize: 14, color: AppTheme.textPrimary, height: 1.3), ), ], ), ), ], ); } }