import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:geolocator/geolocator.dart' hide ServiceStatus;
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:http/http.dart' as http;
import 'package:intl/intl.dart';
import 'package:prosapp_web_app/models/schedules_entity.dart';
import 'package:prosapp_web_app/models/service.dart';
import 'package:prosapp_web_app/models/service_location_preferences.dart';
import 'package:prosapp_web_app/models/service_status.dart';
import 'package:prosapp_web_app/models/usuario.dart';
import 'package:prosapp_web_app/models/usuario_profesional.dart';
import 'package:prosapp_web_app/providers/auth_provider.dart';
import 'package:prosapp_web_app/providers/cities_provider.dart';
import 'package:prosapp_web_app/providers/theme_provider.dart';
import 'package:prosapp_web_app/router/router.dart';
import 'package:prosapp_web_app/services/api_service.dart';
import 'package:prosapp_web_app/services/maps_service.dart';
import 'package:prosapp_web_app/services/navigation_service.dart';
import 'package:prosapp_web_app/services/notifications_service.dart';
import 'package:prosapp_web_app/utils/local_notifications.dart';
import 'package:prosapp_web_app/utils/network_utility.dart';
import 'package:prosapp_web_app/utils/time_of_day_extension.dart';
import 'package:provider/provider.dart';

class DashboardView extends StatefulWidget {
  const DashboardView({super.key});

  @override
  State<DashboardView> createState() => _DashboardViewState();
}

class _DashboardViewState extends State<DashboardView> {
  Usuario? user;

  // Map
  GoogleMapController? _mapController;
  LatLng _mapCenter = const LatLng(4.6097, -74.0817);
  bool _mapsReady = false;
  bool _mapsLoading = true;
  bool _geocoding = false;
  String _currentAddress = '';
  String? _mapsApiKey;

  // Search / autocomplete
  final _searchController = TextEditingController();
  final _searchFocus = FocusNode();
  List<dynamic> _suggestions = [];
  Timer? _debounce;

  // Booking
  UsuarioProfesional? _professional;
  DateTime? _selectedDay;
  TimeOfDay? _selectedHour;
  bool _requesting = false;

  // Throttle reverse geocode on camera idle
  DateTime _lastGeocode = DateTime(0);

  // Ciudad detectada y disponibilidad
  String _detectedCity = '';
  bool _cityAvailable = true;

  @override
  void initState() {
    super.initState();
    user = Provider.of<AuthProvider>(context, listen: false).user;
    _initMaps();
  }

  Future<void> _initMaps() async {
    final ok = await MapsService.load();
    if (!mounted) return;
    try {
      final data = await ApiService.instance.get('/settings/maps-key');
      _mapsApiKey = data['api_key'] as String? ?? '';
    } catch (_) {}
    setState(() {
      _mapsReady = ok;
      _mapsLoading = false;
    });
    if (ok) _detectLocation();
  }

  Future<void> _detectLocation() async {
    try {
      bool serviceEnabled = await Geolocator.isLocationServiceEnabled();
      if (!serviceEnabled) return;

      LocationPermission permission = await Geolocator.checkPermission();
      if (permission == LocationPermission.denied) {
        permission = await Geolocator.requestPermission();
        if (permission == LocationPermission.denied) return;
      }
      if (permission == LocationPermission.deniedForever) return;

      final pos = await Geolocator.getCurrentPosition(
        locationSettings: const LocationSettings(
          accuracy: LocationAccuracy.medium,
          timeLimit: Duration(seconds: 8),
        ),
      );

      final latlng = LatLng(pos.latitude, pos.longitude);
      if (mounted) setState(() => _mapCenter = latlng);
      _mapController?.animateCamera(CameraUpdate.newLatLngZoom(latlng, 16));
      _reverseGeocode(latlng);
    } catch (_) {}
  }

  Future<void> _reverseGeocode(LatLng pos) async {
    if (_mapsApiKey == null || _mapsApiKey!.isEmpty) return;
    final now = DateTime.now();
    if (now.difference(_lastGeocode).inMilliseconds < 800) return;
    _lastGeocode = now;

    setState(() => _geocoding = true);
    try {
      final res = await http.get(Uri.parse(
        'https://maps.googleapis.com/maps/api/geocode/json'
        '?latlng=${pos.latitude},${pos.longitude}'
        '&key=$_mapsApiKey&language=es',
      ));
      if (res.statusCode == 200) {
        final data = jsonDecode(res.body);
        final results = data['results'] as List?;
        if (results != null && results.isNotEmpty) {
          final address = results[0]['formatted_address'] as String;
          final components = results[0]['address_components'] as List? ?? [];
          final city = _extractCity(components);

          final citiesProvider = Provider.of<CitiesProvider>(context, listen: false);
          final available = city.isEmpty || citiesProvider.isCityAvailable(city);

          if (mounted) {
            setState(() {
              _currentAddress = address;
              _searchController.text = address;
              _detectedCity = city;
              _cityAvailable = available;
            });
          }
        }
      }
    } catch (_) {}
    if (mounted) setState(() => _geocoding = false);
  }

  String _extractCity(List components) {
    for (final c in components) {
      final types = List<String>.from(c['types'] ?? []);
      if (types.contains('locality') || types.contains('administrative_area_level_2')) {
        return c['long_name'] as String? ?? '';
      }
    }
    return '';
  }

  Future<void> _geocodeAndMoveMap(String address) async {
    if (_mapsApiKey == null || _mapsApiKey!.isEmpty) return;
    try {
      final res = await http.get(Uri.parse(
        'https://maps.googleapis.com/maps/api/geocode/json'
        '?address=${Uri.encodeComponent(address)}'
        '&key=$_mapsApiKey&language=es',
      ));
      if (res.statusCode == 200) {
        final data = jsonDecode(res.body);
        final results = data['results'] as List?;
        if (results != null && results.isNotEmpty) {
          final loc = results[0]['geometry']['location'];
          final pos = LatLng(
            (loc['lat'] as num).toDouble(),
            (loc['lng'] as num).toDouble(),
          );
          if (mounted) setState(() => _mapCenter = pos);
          _mapController?.animateCamera(CameraUpdate.newLatLngZoom(pos, 16));
        }
      }
    } catch (_) {}
  }

  void _onSearchChanged(String value) {
    _debounce?.cancel();
    if (value.length < 3) {
      setState(() => _suggestions = []);
      return;
    }
    _debounce = Timer(const Duration(milliseconds: 450), () async {
      final uri = Uri.https('admin.prosapp.co', '/autocomplete', {
        'input': value,
        'location': '${_mapCenter.latitude},${_mapCenter.longitude}',
      });
      final response = await NetworkUtility.fetchUrl(uri);
      if (response != null && mounted) {
        final decoded = jsonDecode(response);
        final results = decoded['results'] ?? decoded['predictions'] ?? [];
        setState(() => _suggestions = results is List ? results : []);
      }
    });
  }

  void _selectSuggestion(String address) {
    setState(() {
      _currentAddress = address;
      _searchController.text = address;
      _suggestions = [];
    });
    _searchFocus.unfocus();
    _geocodeAndMoveMap(address);
  }

  Future<void> _selectProfessional() async {
    try {
      final result = await NavigationService.navigateToFuture(Flurorouter.professionalsRoute);
      final prof = result[0] as UsuarioProfesional;
      setState(() {
        _professional = prof;
        _selectedDay = result[1];
        _selectedHour = result[2];
      });
    } catch (_) {}
  }

  Future<void> _requestService() async {
    if (_currentAddress.isEmpty) {
      NotificationsService.showSnackBarError('Mueve el mapa para seleccionar tu dirección');
      return;
    }
    if (_professional == null) {
      NotificationsService.showSnackBarError('Selecciona un profesional');
      return;
    }
    if (_selectedDay == null || _selectedHour == null) {
      NotificationsService.showSnackBarError('Selecciona fecha y hora');
      return;
    }
    setState(() => _requesting = true);
    try {
      final service = Service(
        id: null,
        professionalId: _professional!.user.id,
        professionalScored: false,
        userId: user!.id,
        userScored: false,
        address: _currentAddress,
        aditionalAddress: '',
        latitude: _mapCenter.latitude,
        longitude: _mapCenter.longitude,
        day: _selectedDay.toString(),
        createdAt: DateTime.now().toIso8601String(),
        description: '',
        range1Hour1: _selectedHour!,
        range1Hour2: _selectedHour!.add(hour: 2),
        rate: '',
        status: ServiceStatus.pending,
        location: ServiceLocationPreferences.delivery,
      );
      await ApiService.instance.post('/services', service.toDocument());
      NotificationsService.showSnackbar('Servicio solicitado exitosamente');
      if (_professional!.user.token != null) {
        LocalNotifications.sendPushNotification(
          _professional!.user.token!,
          'Nuevo servicio',
          'Tienes una nueva solicitud de servicio pendiente',
        );
      }
      setState(() {
        _professional = null;
        _selectedDay = null;
        _selectedHour = null;
      });
    } catch (_) {
      NotificationsService.showSnackBarError('Error al solicitar el servicio');
    } finally {
      setState(() => _requesting = false);
    }
  }

  @override
  void dispose() {
    _debounce?.cancel();
    _searchController.dispose();
    _searchFocus.dispose();
    _mapController?.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    if (user == null || _mapsLoading) {
      return const Center(child: CircularProgressIndicator());
    }

    final isDark = context.watch<ThemeProvider>().isDark;
    final cardBg = isDark ? const Color(0xFF1E293B) : Colors.white;
    final cardBorder = isDark ? const Color(0xFF334155) : const Color(0xFFE0E0E0);
    final textColor = isDark ? Colors.white : Colors.black87;
    final subtextColor = isDark ? Colors.white54 : Colors.black54;
    final hintColor = isDark ? Colors.white38 : Colors.grey;
    final inputFill = isDark ? const Color(0xFF0F172A) : Colors.white;

    return GestureDetector(
      onTap: () {
        _searchFocus.unfocus();
        setState(() => _suggestions = []);
      },
      child: Stack(
        children: [
          // ── MAPA ──
          if (_mapsReady)
            GoogleMap(
              initialCameraPosition: CameraPosition(target: _mapCenter, zoom: 14),
              onMapCreated: (c) => _mapController = c,
              onCameraMove: (pos) => _mapCenter = pos.target,
              onCameraIdle: () => _reverseGeocode(_mapCenter),
              myLocationEnabled: true,
              myLocationButtonEnabled: false,
              zoomControlsEnabled: false,
            )
          else
            Container(
              color: const Color(0xFFE8EDF0),
              child: Center(
                child: Padding(
                  padding: const EdgeInsets.all(32),
                  child: Column(
                    mainAxisSize: MainAxisSize.min,
                    children: const [
                      Icon(Icons.map_outlined, size: 56, color: Colors.grey),
                      SizedBox(height: 12),
                      Text(
                        'Google Maps no configurado.\nConfigura la API Key en el panel de administración.',
                        textAlign: TextAlign.center,
                        style: TextStyle(color: Colors.grey, fontSize: 14),
                      ),
                    ],
                  ),
                ),
              ),
            ),

          // ── PIN central fijo ──
          if (_mapsReady)
            Positioned.fill(
              child: IgnorePointer(
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: const [
                    Icon(Icons.location_on, color: Color(0xFF42A4EF), size: 48),
                    SizedBox(height: 20),
                  ],
                ),
              ),
            ),

          // ── BARRA DE BÚSQUEDA FLOTANTE ──
          Positioned(
            top: 16,
            left: 16,
            right: 16,
            child: Column(
              children: [
                Container(
                  decoration: BoxDecoration(
                    color: cardBg,
                    borderRadius: BorderRadius.circular(14),
                    boxShadow: [
                      BoxShadow(
                        color: Colors.black.withOpacity(isDark ? 0.4 : 0.15),
                        blurRadius: 14,
                        offset: const Offset(0, 4),
                      ),
                    ],
                  ),
                  child: TextField(
                    controller: _searchController,
                    focusNode: _searchFocus,
                    onChanged: _onSearchChanged,
                    style: TextStyle(fontSize: 14, color: textColor),
                    decoration: InputDecoration(
                      hintText: 'Busca o mueve el mapa para fijar tu dirección',
                      hintStyle: TextStyle(color: hintColor, fontSize: 13),
                      prefixIcon: _geocoding
                          ? const Padding(
                              padding: EdgeInsets.all(13),
                              child: SizedBox(
                                width: 18,
                                height: 18,
                                child: CircularProgressIndicator(strokeWidth: 2),
                              ),
                            )
                          : const Icon(Icons.search, color: Color(0xFF42A4EF)),
                      suffixIcon: _searchController.text.isNotEmpty
                          ? IconButton(
                              icon: const Icon(Icons.close, size: 18, color: Colors.grey),
                              onPressed: () {
                                _searchController.clear();
                                setState(() {
                                  _suggestions = [];
                                  _currentAddress = '';
                                });
                              },
                            )
                          : null,
                      border: InputBorder.none,
                      contentPadding: const EdgeInsets.symmetric(vertical: 15, horizontal: 4),
                    ),
                  ),
                ),

                // Sugerencias
                if (_suggestions.isNotEmpty)
                  Container(
                    margin: const EdgeInsets.only(top: 4),
                    decoration: BoxDecoration(
                      color: cardBg,
                      borderRadius: BorderRadius.circular(12),
                      boxShadow: [
                        BoxShadow(color: Colors.black.withOpacity(isDark ? 0.4 : 0.12), blurRadius: 10),
                      ],
                    ),
                    child: Column(
                      children: _suggestions.take(5).toList().asMap().entries.map((e) {
                        final item = e.value as Map<String, dynamic>;
                        final addr = (item['formatted_address'] ?? item['description'] ?? item['name'] ?? '').toString();
                        final isLast = e.key == (_suggestions.length - 1).clamp(0, 4);
                        return Column(
                          children: [
                            InkWell(
                              onTap: () => _selectSuggestion(addr),
                              borderRadius: BorderRadius.circular(12),
                              child: Padding(
                                padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 13),
                                child: Row(
                                  children: [
                                    const Icon(Icons.location_on_outlined, size: 18, color: Color(0xFF42A4EF)),
                                    const SizedBox(width: 10),
                                    Expanded(
                                      child: Text(
                                        addr,
                                        style: TextStyle(fontSize: 13, color: textColor),
                                        maxLines: 2,
                                        overflow: TextOverflow.ellipsis,
                                      ),
                                    ),
                                  ],
                                ),
                              ),
                            ),
                            if (!isLast) Divider(height: 1, indent: 16,
                              color: isDark ? Colors.white12 : Colors.grey[100]),
                          ],
                        );
                      }).toList(),
                    ),
                  ),
              ],
            ),
          ),

          // ── MI UBICACIÓN ──
          if (_mapsReady)
            Positioned(
              right: 16,
              bottom: 210,
              child: FloatingActionButton.small(
                heroTag: 'myLoc',
                backgroundColor: Colors.white,
                elevation: 4,
                onPressed: _detectLocation,
                child: const Icon(Icons.my_location, color: Color(0xFF42A4EF), size: 20),
              ),
            ),

          // ── TARJETA INFERIOR ──
          Positioned(
            left: 0,
            right: 0,
            bottom: 0,
            child: Container(
              decoration: BoxDecoration(
                color: cardBg,
                borderRadius: const BorderRadius.vertical(top: Radius.circular(20)),
                boxShadow: [
                  BoxShadow(
                    color: Colors.black.withOpacity(isDark ? 0.4 : 0.13),
                    blurRadius: 18,
                    offset: const Offset(0, -4),
                  ),
                ],
              ),
              padding: const EdgeInsets.fromLTRB(20, 10, 20, 24),
              child: Column(
                mainAxisSize: MainAxisSize.min,
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Center(
                    child: Container(
                      width: 40,
                      height: 4,
                      decoration: BoxDecoration(
                        color: Colors.grey[300],
                        borderRadius: BorderRadius.circular(2),
                      ),
                    ),
                  ),
                  const SizedBox(height: 10),

                  // Dirección actual
                  if (_currentAddress.isNotEmpty)
                    Container(
                      padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
                      margin: const EdgeInsets.only(bottom: 10),
                      decoration: BoxDecoration(
                        color: isDark
                            ? const Color(0xFF42A4EF).withOpacity(0.12)
                            : const Color(0xFFF0F8FF),
                        borderRadius: BorderRadius.circular(8),
                        border: Border.all(color: const Color(0xFF42A4EF).withOpacity(0.35)),
                      ),
                      child: Row(
                        children: [
                          const Icon(Icons.location_on, size: 16, color: Color(0xFF42A4EF)),
                          const SizedBox(width: 8),
                          Expanded(
                            child: Text(
                              _currentAddress,
                              style: TextStyle(fontSize: 12, color: textColor),
                              maxLines: 2,
                              overflow: TextOverflow.ellipsis,
                            ),
                          ),
                        ],
                      ),
                    ),

                  // Profesional
                  GestureDetector(
                    onTap: _selectProfessional,
                    child: Container(
                      padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 12),
                      decoration: BoxDecoration(
                        border: Border.all(
                          color: _professional != null
                              ? const Color(0xFF42A4EF)
                              : cardBorder,
                        ),
                        borderRadius: BorderRadius.circular(10),
                        color: _professional != null
                            ? const Color(0xFF42A4EF).withOpacity(0.1)
                            : (isDark ? const Color(0xFF0F172A) : Colors.grey[50]),
                      ),
                      child: Row(
                        children: [
                          Icon(
                            Icons.person_outline,
                            size: 20,
                            color: _professional != null
                                ? const Color(0xFF42A4EF)
                                : subtextColor,
                          ),
                          const SizedBox(width: 10),
                          Expanded(
                            child: Text(
                              _professional?.user.name ?? 'Seleccionar profesional',
                              style: TextStyle(
                                fontSize: 13,
                                color: _professional != null ? textColor : subtextColor,
                              ),
                            ),
                          ),
                          Icon(Icons.chevron_right, color: subtextColor, size: 18),
                        ],
                      ),
                    ),
                  ),

                  // Fecha y hora
                  if (_selectedDay != null && _selectedHour != null) ...[
                    const SizedBox(height: 8),
                    Container(
                      padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 10),
                      decoration: BoxDecoration(
                        border: Border.all(color: cardBorder),
                        borderRadius: BorderRadius.circular(10),
                        color: isDark ? const Color(0xFF0F172A) : Colors.grey[50],
                      ),
                      child: Row(
                        children: [
                          const Icon(Icons.calendar_today_outlined, size: 17, color: Color(0xFF42A4EF)),
                          const SizedBox(width: 8),
                          Text(
                            DateFormat('dd/MM/yyyy').format(_selectedDay!),
                            style: TextStyle(fontSize: 13, color: textColor),
                          ),
                          const SizedBox(width: 14),
                          const Icon(Icons.access_time, size: 17, color: Color(0xFF42A4EF)),
                          const SizedBox(width: 6),
                          Text(
                            ScheduleEntity.getFormatTime(_selectedHour!) ?? '',
                            style: TextStyle(fontSize: 13, color: textColor),
                          ),
                          const Spacer(),
                          GestureDetector(
                            onTap: () => setState(() {
                              _selectedDay = null;
                              _selectedHour = null;
                              _professional = null;
                            }),
                            child: Icon(Icons.close, size: 18, color: subtextColor),
                          ),
                        ],
                      ),
                    ),
                  ],

                  const SizedBox(height: 12),

                  // Aviso ciudad no disponible
                  if (!_cityAvailable && _detectedCity.isNotEmpty)
                    Container(
                      width: double.infinity,
                      margin: const EdgeInsets.only(bottom: 10),
                      padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 12),
                      decoration: BoxDecoration(
                        color: const Color(0xFFFFF3CD),
                        borderRadius: BorderRadius.circular(10),
                        border: Border.all(color: const Color(0xFFFFC107)),
                      ),
                      child: Row(
                        children: [
                          const Icon(Icons.location_off_outlined, color: Color(0xFF856404), size: 20),
                          const SizedBox(width: 10),
                          Expanded(
                            child: Column(
                              crossAxisAlignment: CrossAxisAlignment.start,
                              children: [
                                const Text(
                                  'Servicio no disponible en tu ciudad',
                                  style: TextStyle(
                                    color: Color(0xFF856404),
                                    fontWeight: FontWeight.w600,
                                    fontSize: 13,
                                  ),
                                ),
                                Text(
                                  'Actualmente no operamos en $_detectedCity. Mueve el mapa a una ciudad disponible.',
                                  style: const TextStyle(color: Color(0xFF856404), fontSize: 11),
                                ),
                              ],
                            ),
                          ),
                        ],
                      ),
                    ),

                  SizedBox(
                    width: double.infinity,
                    child: ElevatedButton(
                      onPressed: (_requesting || !_cityAvailable) ? null : _requestService,
                      style: ElevatedButton.styleFrom(
                        backgroundColor: const Color(0xFF42A4EF),
                        foregroundColor: Colors.white,
                        disabledBackgroundColor: Colors.grey[200],
                        padding: const EdgeInsets.symmetric(vertical: 15),
                        shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
                        elevation: 0,
                      ),
                      child: _requesting
                          ? const SizedBox(
                              width: 20,
                              height: 20,
                              child: CircularProgressIndicator(color: Colors.white, strokeWidth: 2),
                            )
                          : const Text(
                              'Solicitar servicio',
                              style: TextStyle(fontSize: 15, fontWeight: FontWeight.w600),
                            ),
                    ),
                  ),
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }
}
