import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:geocoding/geocoding.dart';
import 'package:geolocator/geolocator.dart';
import 'package:go_router/go_router.dart';
import 'package:latlong2/latlong.dart';
import 'package:http/http.dart' as http;
import 'package:niogu_ecommerce_v1/core/constant/app_color.dart';
import 'package:niogu_ecommerce_v1/core/constant/app_font_size.dart';
import 'package:niogu_ecommerce_v1/core/router/app_route.dart';
import 'package:niogu_ecommerce_v1/core/utils/log_message.dart';
import 'package:niogu_ecommerce_v1/core/widgets/triangle_painter.dart';
import 'package:niogu_ecommerce_v1/features/account/domain/entities/account.dart';
import 'package:niogu_ecommerce_v1/features/account/presentation/providers/account_provider.dart';
import 'package:sizer/sizer.dart';

class MapAddressScreen extends ConsumerStatefulWidget {
  const MapAddressScreen({super.key});

  @override
  ConsumerState<MapAddressScreen> createState() => _MapAddressScreenState();
}

class _MapAddressScreenState extends ConsumerState<MapAddressScreen> {
  final MapController _mapController = MapController();

  LatLng _selectedLocation = const LatLng(-6.2000, 106.8166);

  String _fullAddress = "";

  bool _isSearching = false;

  bool _isLoadingMap = false;

  List<dynamic> _suggestions = [];

  Timer? _debounce;

  @override
  void initState() {
    // TODO: implement initState
    super.initState();

    WidgetsBinding.instance.addPostFrameCallback((_) {
      _fetchSelectedAddress();
    });
  }

  void _fetchSelectedAddress() async {
    final selectedAddress = ref.read(selectedAddressProvider);

    if (selectedAddress != null) {
      await _updateLocation(
        LatLng(selectedAddress.latitude, selectedAddress.longitude),
      );
    }
  }

  void _onSearchChanged(String query) {
    if (_debounce?.isActive ?? false) _debounce?.cancel();

    if (query.isEmpty) {
      setState(() => _suggestions = []);
      return;
    }

    _debounce = Timer(const Duration(milliseconds: 800), () async {
      setState(() => _isSearching = true);

      try {
        final url = Uri.parse(
          'https://nominatim.openstreetmap.org/search?q=$query&format=json&limit=5&countrycodes=id',
        );

        final response = await http.get(
          url,
          headers: {
            'User-Agent': 'NioguEcommerceApp/1.0 (niaganusantara@gmail.com)',
            'Accept-Language': 'id',
          },
        );

        if (response.statusCode == 200) {
          setState(() {
            _suggestions = json.decode(response.body);
            _isSearching = false;
          });
        }
      } catch (e, st) {
        LogMessage.log.e(e.toString(), error: e, stackTrace: st);
        setState(() => _isSearching = false);
      }
    });
  }

  Future<void> _getCurrentPosition() async {
    setState(() => _isLoadingMap = true);

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

    Position position = await Geolocator.getCurrentPosition();
    final newLatLng = LatLng(position.latitude, position.longitude);

    await _updateLocation(newLatLng);
  }

  Future<void> _updateLocation(LatLng point) async {
    setState(() {
      _selectedLocation = point;
      _isLoadingMap = true;
    });

    _mapController.move(point, 16.0);

    try {
      List<Placemark> placemarks = await placemarkFromCoordinates(
        point.latitude,
        point.longitude,
      );
      if (placemarks.isNotEmpty) {
        final place = placemarks[0];
        setState(() {
          _fullAddress =
              "${place.street}, ${place.subLocality}, ${place.locality}, ${place.subAdministrativeArea}";
          _isLoadingMap = false;
          _suggestions = [];
        });
      }
    } catch (e) {
      setState(() => _isLoadingMap = false);
    }
  }

  void _selectedAddress() {
    ref.read(selectedAddressProvider.notifier).state = SelectedAddress(
      fullAddress: _fullAddress,
      latitude: _selectedLocation.latitude,
      longitude: _selectedLocation.longitude,
    );
  }

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(
      builder: (context, constraints) {
        return SafeArea(
          top: false,
          bottom: true,
          right: false,
          left: false,
          child: Scaffold(
            body: Stack(
              children: [
                FlutterMap(
                  mapController: _mapController,
                  options: MapOptions(
                    initialCenter: _selectedLocation,
                    initialZoom: 16.0,
                    onTap: (_, point) => _updateLocation(point),
                  ),
                  children: [
                    TileLayer(
                      urlTemplate:
                          'https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png',
                      subdomains: const ['a', 'b', 'c', 'd'],
                    ),
                    MarkerLayer(
                      markers: [
                        Marker(
                          point: _selectedLocation,
                          width: 80.w,
                          height: 15.h,
                          alignment: Alignment.topCenter,
                          child: Column(
                            mainAxisSize: MainAxisSize.min,
                            children: [
                              if (_fullAddress.isNotEmpty) ...[
                                _buildAddressBubble(),
                                CustomPaint(
                                  size: Size(5.w, 2.5.w),
                                  painter: TrianglePainter(Colors.white),
                                ),
                                Icon(
                                  Icons.location_on,
                                  color: AppColor.primaryColor,
                                  size: 10.w,
                                ),
                              ],
                            ],
                          ),
                        ),
                      ],
                    ),
                  ],
                ),

                Positioned(
                  top: 6.h,
                  left: 5.w,
                  right: 5.w,
                  child: Column(
                    children: [
                      _buildSearchBar(),
                      if (_suggestions.isNotEmpty || _isSearching)
                        _buildSuggestionList(),
                    ],
                  ),
                ),

                Positioned(
                  bottom: 4.h,
                  left: 5.w,
                  right: 5.w,
                  child: Column(
                    children: [
                      Align(
                        alignment: Alignment.centerRight,
                        child: FloatingActionButton(
                          mini: true,
                          backgroundColor: Colors.white,
                          onPressed: _getCurrentPosition,
                          child: Icon(
                            Icons.my_location,
                            color: AppColor.primaryColor,
                          ),
                        ),
                      ),
                      SizedBox(height: 2.h),
                      ElevatedButton(
                        onPressed: _fullAddress.isEmpty
                            ? null
                            : () {
                                _selectedAddress();
                                context.pushReplacementNamed(
                                  AppRoute.saveAddressScreen,
                                );
                              },
                        style: ElevatedButton.styleFrom(
                          minimumSize: Size(double.infinity, 6.h),
                          backgroundColor: AppColor.primaryColor,
                          shape: RoundedRectangleBorder(
                            borderRadius: BorderRadius.circular(2.5.w),
                          ),
                        ),
                        child: Text(
                          "Pilih Lokasi Ini",
                          style: TextStyle(
                            color: Colors.white,
                            fontWeight: FontWeight.bold,
                            fontSize: AppFontSize.medium.sp,
                          ),
                        ),
                      ),
                    ],
                  ),
                ),

                if (_isLoadingMap)
                  Center(
                    child: CircularProgressIndicator(
                      color: AppColor.primaryColor,
                    ),
                  ),
              ],
            ),
          ),
        );
      },
    );
  }

  Widget _buildSearchBar() {
    return Row(
      children: [
        GestureDetector(
          onTap: () => context.pop(),
          child: Padding(
            padding: EdgeInsets.all(2.w),
            child: CircleAvatar(
              maxRadius: 5.w,
              minRadius: 5.w,
              backgroundColor: Colors.white.withOpacity(0.9),
              child: Center(
                child: Icon(Icons.arrow_back, color: Colors.black, size: 6.w),
              ),
            ),
          ),
        ),
        Expanded(
          child: Container(
            decoration: BoxDecoration(
              color: Colors.white,
              borderRadius: BorderRadius.circular(2.5.w),
              boxShadow: [
                BoxShadow(
                  color: Colors.black12,
                  blurRadius: 10,
                  offset: const Offset(0, 5),
                ),
              ],
            ),
            child: TextField(
              onChanged: _onSearchChanged,
              style: TextStyle(fontSize: AppFontSize.small.sp),
              decoration: InputDecoration(
                hintText: "Cari Lokasi...",
                hintStyle: TextStyle(fontSize: AppFontSize.small.sp),
                prefixIcon: Icon(Icons.search, size: 5.w),
                suffixIcon: _isSearching
                    ? Transform.scale(
                        scale: 0.5,
                        child: CircularProgressIndicator(
                          color: AppColor.primaryColor,
                        ),
                      )
                    : null,
                border: InputBorder.none,
                contentPadding: EdgeInsets.symmetric(vertical: 2.h),
              ),
            ),
          ),
        ),
      ],
    );
  }

  Widget _buildSuggestionList() {
    return Container(
      margin: EdgeInsets.only(top: 1.h),
      constraints: BoxConstraints(maxHeight: 30.h),
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(2.5.w),
      ),
      child: ListView.builder(
        shrinkWrap: true,
        padding: EdgeInsets.zero,
        itemCount: _suggestions.length,
        itemBuilder: (context, index) {
          final item = _suggestions[index];
          return ListTile(
            leading: Icon(Icons.location_on_outlined, size: 5.w),
            title: Text(
              item['display_name'],
              style: TextStyle(fontSize: (AppFontSize.small - 1.25).sp),
            ),
            onTap: () {
              final lat = double.parse(item['lat']);
              final lon = double.parse(item['lon']);
              _updateLocation(LatLng(lat, lon));
            },
          );
        },
      ),
    );
  }

  Widget _buildAddressBubble() {
    return Container(
      padding: EdgeInsets.all(2.w),
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(2.w),
        boxShadow: const [BoxShadow(color: Colors.black12, blurRadius: 4)],
      ),
      child: Text(
        _fullAddress,
        maxLines: 2,
        textAlign: TextAlign.center,
        style: TextStyle(
          fontSize: (AppFontSize.small - 1.25).sp,
          fontWeight: FontWeight.w500,
        ),
      ),
    );
  }
}
