import 'dart:async';
import 'dart:convert';
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:flutter/material.dart';
import 'package:flutter_polyline_points/flutter_polyline_points.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:monk_food/controller/data_importer.dart';

class MapProvider with ChangeNotifier {
  List<Marker> markers = [];
  PolylinePoints polylinePoints = PolylinePoints();
  Map<PolylineId, Polyline> polylines = {};
  late GoogleMapController googleMapController;

  // void initialize(List<LatLng> locs) {
  //   markers = [];
  //   for (var loc in locs) {
  //     addMarker(loc);
  //   }
  //   cacheMarkers();
  // }

  void initialize(List<LatLng> locs) {
    markers.clear();
    int a = 1;

    for (var loc in locs) {
      addMarker(loc);
      print("loc $a: ${loc.longitude} ${loc.latitude}");
      a += 1;
    }

    if (markers.length > 1) {
      getDirections();
    }

    cacheMarkers();
  }

  void setMapController(GoogleMapController controller) {
    googleMapController = controller;
    notifyListeners();
  }

  void addMarker(LatLng latLng) {
    markers.add(
      Marker(
        consumeTapEvents: true,
        markerId: MarkerId(latLng.toString()),
        position: latLng,
        onTap: () {
          markers.removeWhere((element) => element.markerId == MarkerId(latLng.toString()));
          if (markers.length > 1) {
            getDirections();
          } else {
            polylines.clear();
          }
          cacheMarkers();
          cachePolylines();
          notifyListeners();
        },
      ),
    );
    if (markers.length > 1) {
      getDirections();
    }
    cacheMarkers();
    notifyListeners();
  }

  Future<void> getDirections() async {
    final connectivityResult = await Connectivity().checkConnectivity();

    if (connectivityResult.contains(ConnectivityResult.none)) {
      print("No internet connection. Loading cached data...");
      await loadCachedPolylines();
      notifyListeners();
      return;
    }

    List<LatLng> polylineCoordinates = [];
    List<PolylineWayPoint> polylineWayPoints = [];
    for (var marker in markers) {
      polylineWayPoints.add(PolylineWayPoint(
        location: "${marker.position.latitude},${marker.position.longitude}",
        stopOver: true,
      ));
    }

    try {
      PolylineResult result = await polylinePoints.getRouteBetweenCoordinates(
        request: PolylineRequest(
          origin: PointLatLng(markers.first.position.latitude, markers.first.position.longitude),
          destination: PointLatLng(markers.last.position.latitude, markers.last.position.longitude),
          mode: TravelMode.driving,
          wayPoints: polylineWayPoints,
        ),
        googleApiKey: googleMapApiKey,
      );

      if (result.points.isNotEmpty) {
        for (var point in result.points) {
          polylineCoordinates.add(LatLng(point.latitude, point.longitude));
        }
      } else {
        print(result.errorMessage);
      }

      addPolyLine(polylineCoordinates);
      cachePolylines();
    } catch (e) {
      print("Failed to fetch directions: $e");
      // Fallback to cached data if available
      await loadCachedPolylines();
    }

    notifyListeners();
  }

  void addPolyLine(List<LatLng> polylineCoordinates) {
    PolylineId id = PolylineId("poly");
    Polyline polyline = Polyline(
      polylineId: id,
      color: Colors.red,
      points: polylineCoordinates,
      width: 4,
    );
    polylines[id] = polyline;
    notifyListeners();
  }

  // Cache markers to SharedPreferences
  Future<void> cacheMarkers() async {
    final prefs = await SharedPreferences.getInstance();
    List<String> markerData = markers.map((marker) {
      return jsonEncode({
        'latitude': marker.position.latitude,
        'longitude': marker.position.longitude,
      });
    }).toList();
    await prefs.setStringList('cachedMarkers', markerData);
  }

  // Load cached markers from SharedPreferences
  Future<void> loadCachedMarkers() async {
    final prefs = await SharedPreferences.getInstance();
    List<String>? markerData = prefs.getStringList('cachedMarkers');
    if (markerData != null) {
      markers = markerData.map((data) {
        Map<String, dynamic> markerMap = jsonDecode(data);
        return Marker(
          markerId: MarkerId('${markerMap['latitude']},${markerMap['longitude']}'),
          position: LatLng(markerMap['latitude'], markerMap['longitude']),
        );
      }).toList();
      notifyListeners();
    }
  }

  // Cache polylines to SharedPreferences
  Future<void> cachePolylines() async {
    final prefs = await SharedPreferences.getInstance();
    List<String> polylineData = polylines.values.map((polyline) {
      return jsonEncode({
        'polylineId': polyline.polylineId.value,
        'points': polyline.points
            .map((point) => {
                  'latitude': point.latitude,
                  'longitude': point.longitude,
                })
            .toList(),
      });
    }).toList();
    await prefs.setStringList('cachedPolylines', polylineData);
  }

  // Load cached polylines from SharedPreferences
  Future<void> loadCachedPolylines() async {
    final prefs = await SharedPreferences.getInstance();
    List<String>? polylineData = prefs.getStringList('cachedPolylines');
    if (polylineData != null) {
      polylines.clear();
      for (var data in polylineData) {
        Map<String, dynamic> polylineMap = jsonDecode(data);
        List<LatLng> points = (polylineMap['points'] as List).map((point) {
          return LatLng(point['latitude'], point['longitude']);
        }).toList();
        addPolyLine(points);
      }
      notifyListeners();
    }
  }
}

with,this,code,the,map,dissapeared,when,get,direction,failed