import 'package:flutter/material.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_map/flutter_map.dart'; import 'package:latlong2/latlong.dart'; import 'package:dio/dio.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import '../../core/models/address_create_request.dart'; import '../../core/models/colonia.dart'; import '../home/colonias_data.dart'; import '../../core/theme/app_theme.dart'; import '../../core/widgets/app_widgets.dart'; import '../../core/constants/auth_constants.dart'; import 'colonias_provider.dart'; import '../../core/network/api_client.dart'; const Map _cpToColonia = { '38000': 'Zona Centro', '38060': 'Las Arboledas', '38027': 'San Juanico', '38037': 'Los Olivos', '38090': 'Rancho Seco', '38080': 'Las Insurgentes', '38086': 'Trojes', }; class NewAddressPage extends ConsumerStatefulWidget { const NewAddressPage({super.key}); @override ConsumerState createState() => _NewAddressPageState(); } class _NewAddressPageState extends ConsumerState { final _formKey = GlobalKey(); final _labelController = TextEditingController(); final _cpCtrl = TextEditingController(); final _streetController = TextEditingController(); Colonia? _selectedColonia; String _tipoInmueble = 'Casa'; final _mapController = MapController(); LatLng? _selectedLocation; @override void dispose() { _labelController.dispose(); _cpCtrl.dispose(); _streetController.dispose(); _mapController.dispose(); super.dispose(); } Future _fetchStreetName(LatLng latlng) async { setState(() => _selectedLocation = latlng); try { final dio = Dio(); final response = await dio.get( 'https://nominatim.openstreetmap.org/reverse', queryParameters: { 'lat': latlng.latitude, 'lon': latlng.longitude, 'format': 'json', 'addressdetails': 1, }, options: kIsWeb ? null : Options(headers: {'User-Agent': 'com.onlineshack.recolecta'}), ); if (response.data != null && response.data['address'] != null) { final address = response.data['address']; final road = address['road'] ?? address['pedestrian'] ?? address['street'] ?? ''; final houseNumber = address['house_number'] ?? ''; if (road.isNotEmpty) { setState(() { _streetController.text = '$road $houseNumber'.trim(); }); } } } catch (e) { debugPrint('Aviso: Error al obtener nombre de la calle de OSM: $e'); } } void _validarCP(String cp, List colonias) { if (cp.length != 5) { if (_selectedColonia != null) { setState(() { _selectedColonia = null; _selectedLocation = null; _streetController.clear(); }); } return; } final nombre = _cpToColonia[cp]; if (nombre == null) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text( 'Código postal fuera de nuestra zona de servicio actual.', ), backgroundColor: AppTheme.danger, ), ); setState(() { _selectedColonia = null; _selectedLocation = null; }); return; } final backendC = colonias .where((c) => c.nombre.toLowerCase() == nombre.toLowerCase()) .firstOrNull; if (backendC == null) return; setState(() { _selectedColonia = backendC; _selectedLocation = kColoniasCoordinates[nombre]; }); FocusScope.of(context).unfocus(); // Cierra el teclado } Future _saveAddress() async { if (!(_formKey.currentState?.validate() ?? false)) { return; } if (_selectedColonia == null) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Ingresa un código postal válido')), ); return; } try { final dio = ref.read(apiClientProvider); await dio.post( '/addresses', data: { 'label': _labelController.text.trim(), 'calle': _streetController.text.trim(), 'colonia': _selectedColonia!.nombre, }, ); if (mounted) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Domicilio agregado exitosamente')), ); Navigator.pop( context, true, ); // Devuelve true para recargar la lista en la pantalla anterior } } catch (e) { debugPrint('Error al guardar domicilio: $e'); if (mounted) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Error al guardar el domicilio'), backgroundColor: AppTheme.danger, ), ); } } } @override Widget build(BuildContext context) { final baseCenter = _selectedColonia != null ? kColoniasCoordinates[_selectedColonia!.nombre] ?? const LatLng(20.5222, -100.8123) : const LatLng(20.5222, -100.8123); final mapCenter = _selectedLocation ?? baseCenter; final coloniasAsync = ref.watch(coloniasProvider); final coloniasList = coloniasAsync.value ?? []; return Scaffold( appBar: AppBar(title: const Text('Nuevo domicilio')), body: SafeArea( child: ListView( padding: const EdgeInsets.all(24), children: [ Form( key: _formKey, child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ AppFormField( label: 'Etiqueta', hint: 'Ej. Casa de mis padres, Oficina...', controller: _labelController, validator: (value) => (value == null || value.trim().isEmpty) ? 'Ingresa una etiqueta' : null, ), const SizedBox(height: 16), const Text( 'Selección de domicilio', style: TextStyle( fontSize: 12, fontWeight: FontWeight.w500, color: AppTheme.textSecondary, ), ), Row( children: [ Expanded( child: Material( color: Colors.transparent, child: RadioListTile( contentPadding: const EdgeInsets.symmetric( horizontal: 4, ), visualDensity: const VisualDensity( horizontal: -4, vertical: -4, ), title: const Text( 'Casa', style: TextStyle(fontSize: 14), ), value: 'Casa', groupValue: _tipoInmueble, onChanged: (v) { setState(() => _tipoInmueble = v!); if (_labelController.text.trim().isEmpty || _labelController.text == 'Mi Negocio') { _labelController.text = 'Mi Casa'; } }, ), ), ), Expanded( child: Material( color: Colors.transparent, child: RadioListTile( contentPadding: const EdgeInsets.symmetric( horizontal: 4, ), visualDensity: const VisualDensity( horizontal: -4, vertical: -4, ), title: const Text( 'Negocio', style: TextStyle(fontSize: 14), ), value: 'Negocio', groupValue: _tipoInmueble, onChanged: (v) { setState(() => _tipoInmueble = v!); if (_labelController.text.trim().isEmpty || _labelController.text == 'Mi Casa') { _labelController.text = 'Mi Negocio'; } }, ), ), ), ], ), const SizedBox(height: 16), AppFormField( label: 'Código Postal', hint: 'Ej. 38000', controller: _cpCtrl, keyboardType: TextInputType.number, onChanged: (v) => _validarCP(v, coloniasList), ), if (_selectedColonia != null) ...[ const SizedBox(height: 16), Container( padding: const EdgeInsets.all(14), decoration: BoxDecoration( color: AppTheme.primaryLight.withValues(alpha: 0.5), borderRadius: BorderRadius.circular(AppTheme.radiusSm), border: Border.all(color: AppTheme.primaryMid), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ const Icon( Icons.check_circle_outline, color: AppTheme.primary, size: 18, ), const SizedBox(width: 8), Expanded( child: Text( 'Colonia: ${_selectedColonia!.nombre}', style: const TextStyle( fontWeight: FontWeight.w600, color: AppTheme.primaryDark, ), ), ), ], ), const SizedBox(height: 8), Text( 'Horario ${_selectedColonia!.turno?.toLowerCase() ?? 'asignado'}', style: const TextStyle( fontSize: 13, color: AppTheme.textPrimary, ), ), Text( _selectedColonia!.horarioEstimado ?? 'Sin horario especificado', style: const TextStyle( fontSize: 14, fontWeight: FontWeight.bold, color: AppTheme.textPrimary, ), ), ], ), ), const SizedBox(height: 14), AppFormField( label: 'Calle y número', hint: 'Av. Insurgentes 245', controller: _streetController, validator: (value) => (value == null || value.trim().isEmpty) ? 'Ingresa la calle' : null, ), const SizedBox(height: 16), const Text( 'Toca el mapa para ubicar tu domicilio exacto:', style: TextStyle( fontSize: 12, fontWeight: FontWeight.w500, color: AppTheme.textSecondary, ), ), const SizedBox(height: 8), Container( height: 200, decoration: BoxDecoration( borderRadius: BorderRadius.circular(AppTheme.radiusSm), border: Border.all(color: AppTheme.border), ), clipBehavior: Clip.hardEdge, child: FlutterMap( mapController: _mapController, options: MapOptions( initialCenter: mapCenter, initialZoom: 15.0, onTap: (_, latlng) => _fetchStreetName(latlng), ), children: [ TileLayer( urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png', userAgentPackageName: 'com.onlineshack.recolecta', ), if (_selectedLocation != null) MarkerLayer( markers: [ Marker( point: _selectedLocation!, width: 40, height: 40, child: const Icon( Icons.location_on, color: AppTheme.danger, size: 40, ), ), ], ), ], ), ), ] else ...[ const SizedBox(height: 24), const Center( child: Text( 'Ingresa un código postal con servicio\npara asignar tu colonia.', textAlign: TextAlign.center, style: TextStyle( color: AppTheme.textSecondary, fontSize: 13, ), ), ), ], const SizedBox(height: 24), SizedBox( height: 52, child: FilledButton( onPressed: _saveAddress, child: const Text('Guardar domicilio'), ), ), ], ), ), ], ), ), ); } }