import 'dart:async';

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:google_polyline_algorithm/google_polyline_algorithm.dart';
import 'package:ride/constant/box_name.dart';
import 'package:ride/constant/colors.dart';
import 'package:ride/controller/firebase/firbase_messge.dart';
import 'package:ride/controller/functions/location_controller.dart';
import 'package:ride/main.dart';
import 'package:ride/views/Rate/rate_passenger.dart';

import '../../../constant/credential.dart';
import '../../../constant/links.dart';
import '../../functions/crud.dart';

class MapDriverController extends GetxController {
  bool isLoading = true;
  List data = [];
  LatLngBounds? boundsData;
  BitmapDescriptor carIcon = BitmapDescriptor.defaultMarker;
  final List<LatLng> polylineCoordinates = [];
  List<Polyline> polyLines = [];
  Set<Marker> markers = {};
  late String passengerLocation;
  late String duration;
  late String distance;
  late String name;
  late String phone;
  late String rideId;
  late String paymentAmount;
  late String paymentMethod;
  late String passengerId;
  late String driverId;
  late String tokenPassenger;
  late String durationToPassenger;
  late String walletChecked;
  late String direction;
  late String durationOfRideValue;
  late String status;
  bool isPassengerInfoWindow = false;
  bool isBtnRideBegin = false;
  bool isRideFinished = false;
  bool isRideStarted = false;
  double passengerInfoWindow = Get.height * .32;
  double progress = 0;
  double progressToPassenger = 0;
  bool isRideBegin = false;
  int progressTimerToShowPassengerInfoWindowFromDriver = 25;
  int remainingTimeToShowPassengerInfoWindowFromDriver = 25;
  int remainingTimeToPassenger = 60;
  bool isDriverNearPassengerStart = false;
  GoogleMapController? mapController;
  late LatLng myLocation;
  int remainingTimeTimerRideBegin = 60;
  String stringRemainingTimeRideBegin = '';
  double progressTimerRideBegin = 0;
  late Timer timer;

  void onMapCreated(GoogleMapController controller) {
    LocationController locationController = Get.find<LocationController>();
    myLocation = locationController.myLocation;
    mapController = controller;
    controller.getVisibleRegion();
    controller.animateCamera(
      CameraUpdate.newLatLngZoom(myLocation, 15),
    );
    update();

    // Set up a timer or interval to trigger the marker update every 3 seconds.
    timer = Timer.periodic(const Duration(seconds: 3), (_) {
      updateMarker();
    });
  }

  void changeStatusDriver() {
    status = 'On';
    update();
  }

  takeSnapMap() {
    mapController!.takeSnapshot();
  }

  @override
  void dispose() {
    mapController!.dispose();
    super.dispose();
  }

  void checkIsDriverNearPassenger() async {
    if (isDriverNearPassengerStart) {
      Timer.periodic(const Duration(seconds: 3), (timer) {
        String driverLat =
            Get.find<LocationController>().myLocation.latitude.toString();
        String driverLng =
            Get.find<LocationController>().myLocation.longitude.toString();

        // Replace "passengerLat" and "passengerLng" with the actual passenger's location
        String passengerLat = passengerLocation; // Set the passenger's latitude
        String passengerLng = ""; // Set the passenger's longitude
      });
    }
  }

  void clearPolyline() {
    polyLines = [];
    polylineCoordinates.clear();
    update();
  }

  void changeRideToBeginToPassenger() {
    isRideBegin = true;
    passengerInfoWindow = Get.height * .22;
    update();
  }

  void startTimerToShowPassengerInfoWindowFromDriver() async {
    for (int i = 0;
        i <= progressTimerToShowPassengerInfoWindowFromDriver;
        i++) {
      await Future.delayed(const Duration(seconds: 1));
      progress = i / progressTimerToShowPassengerInfoWindowFromDriver;
      remainingTimeToShowPassengerInfoWindowFromDriver =
          progressTimerToShowPassengerInfoWindowFromDriver - i;
      if (remainingTimeToShowPassengerInfoWindowFromDriver == 0) {
        isPassengerInfoWindow = true;
        print(isPassengerInfoWindow);
        update();
        startTimerToShowDriverToPassengerDuration();
      }
      print(isPassengerInfoWindow);
      print(remainingTimeToShowPassengerInfoWindowFromDriver);
      update();
    }
  }

  String stringRemainingTimeToPassenger = '';
  void startTimerToShowDriverToPassengerDuration() async {
    for (int i = 0; i <= int.parse(durationToPassenger); i++) {
      await Future.delayed(const Duration(seconds: 1));
      progressToPassenger = i / int.parse(durationToPassenger);
      remainingTimeToPassenger = int.parse(durationToPassenger) - i;
      if (remainingTimeToPassenger == 0) {
        isBtnRideBegin = true;
        print(isBtnRideBegin);
        update();
      }
      print(isBtnRideBegin);
      print(remainingTimeToPassenger);

      int minutes = (remainingTimeToPassenger / 60).floor();
      int seconds = remainingTimeToPassenger % 60;
      stringRemainingTimeToPassenger =
          '$minutes:${seconds.toString().padLeft(2, '0')}';

      update();
    }
  }

  void driverGoToPassenger() async {
    changeRideToBeginToPassenger();
    await CRUD().post(link: AppLink.updateRides, payload: {
      'id': rideId,
      'driverGoToPassengerTime': DateTime.now().toString(),
      'status': 'Applied'
    });
    FirebaseMessagesController().sendNotificationToAnyWithoutData(
        'DriverIsGoingToPassenger',
        box.read(BoxName.name).toString(),
        tokenPassenger);
  }

  void startRideFromDriver() async {
    changeRideToBeginToPassenger();
    isPassengerInfoWindow = false;
    isRideStarted = true;
    isRideFinished = false;
    box.write(BoxName.statusDriverLocation, 'on');

    update();
    await CRUD().post(link: AppLink.addDriverpayment, payload: {
      'rideId': rideId,
      'amount': paymentAmount,
      'payment_method': paymentMethod,
      'passengerID': passengerId,
      'driverID': box.read(BoxName.driverID).toString(),
    });
    await CRUD().post(link: AppLink.updateRides, payload: {
      'id': rideId,
      'rideTimeStart': DateTime.now().toString(),
      'status': 'Begin'
    });
    rideIsBeginPassengerTimer();
    // FirebaseMessagesController().sendNotificationToAnyWithoutData(
    //     'RideIsBegin', box.read(BoxName.name).toString(), tokenPassenger);
  }

  void finishRideFromDriver() async {
    isRideFinished = true;
    isRideStarted = false;
    box.write(BoxName.statusDriverLocation, 'off');
    // changeRideToBeginToPassenger();
    await CRUD().post(link: AppLink.updateRides, payload: {
      'id': rideId,
      'rideTimeFinish': DateTime.now().toString(),
      'status': 'Finished'
    });
    Get.back();
    Future.delayed(const Duration(milliseconds: 300));
    Get.to(() => RatePassenger(), arguments: {
      'rideId': rideId,
      'passengerId': passengerId,
      'driverId': driverId
    });
    // FirebaseMessagesController().sendNotificationToAnyWithoutData(
    //     'isRideFinished', box.read(BoxName.name).toString(), tokenPassenger);
  }

  void rideIsBeginPassengerTimer() async {
    // print('mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm');
    // print(durationOfRideValue);
    int durationOfRide = int.parse(durationOfRideValue);

    for (int i = 0; i <= durationOfRide; i++) {
      await Future.delayed(const Duration(seconds: 1));
      progressTimerRideBegin = i / durationOfRide;
      remainingTimeTimerRideBegin = durationOfRide - i;

      int minutes = (remainingTimeTimerRideBegin / 60).floor();
      int seconds = remainingTimeTimerRideBegin % 60;
      stringRemainingTimeRideBegin =
          '$minutes:${seconds.toString().padLeft(2, '0')}';
      update();
    }
  }

  void updateMarker() {
    // Remove the existing marker with the ID `MyLocation`.
    markers.remove(MarkerId('MyLocation'.tr));

    // Add a new marker with the ID `MyLocation` at the current location of the user.
    LocationController locationController = Get.find<LocationController>();
    myLocation = locationController.myLocation;
    markers.add(
      Marker(
        markerId: MarkerId('MyLocation'.tr),
        position: locationController.myLocation,
        draggable: true,
        icon: carIcon,
        // infoWindow: const InfoWindow(
        //   title: 'Time',
        // ),
      ),
    );

    // Update the `markers` set and call the `update()` method on the controller to notify the view that the marker position has changed.
    update();

    // No recursive call here. The marker update will be triggered externally.

    // Optionally, you can animate the camera to the new location after updating the marker.
    mapController!.animateCamera(
      CameraUpdate.newLatLng(locationController.myLocation),
    );
  }

  void addCustomCarIcon() {
    ImageConfiguration config = ImageConfiguration(
      size: Size(Get.width * .6, Get.height * .6),
      // scale: 1.0,
    );
    BitmapDescriptor.fromAssetImage(config, 'assets/images/car.png')
        .then((value) {
      carIcon = value;
      update();
    });
  }

  getMap(String origin, destination) async {
    isLoading = false;

    update();

    var url =
        ('${AppLink.googleMapsLink}directions/json?&language=en&avoid=tolls|ferries&destination=$destination&origin=$origin&key=${AppCredintials.mapAPIKEY}');

    var response = await CRUD().getGoogleApi(link: url, payload: {});
    data = response['routes'][0]['legs'];
    print(data);
    final points =
        decodePolyline(response["routes"][0]["overview_polyline"]["points"]);
    for (int i = 0; i < points.length; i++) {
      double lat = points[i][0].toDouble();
      double lng = points[i][1].toDouble();
      polylineCoordinates.add(LatLng(lat, lng));
    }
    if (polyLines.isNotEmpty) {
      clearPolyline();
      var polyline = Polyline(
        polylineId: PolylineId(response["routes"][0]["summary"]),
        points: polylineCoordinates,
        width: 10,
        color: AppColor.blueColor,
      );
      polyLines.add(polyline);
      // rideConfirm = false;
      update();
    } else {
      var polyline = Polyline(
        polylineId: PolylineId(response["routes"][0]["summary"]),
        points: polylineCoordinates,
        width: 10,
        color: AppColor.blueColor,
      );

      polyLines.add(polyline);
      // rideConfirm = false;
      update();
    }
  }

  void changePassengerInfoWindow() {
    isPassengerInfoWindow = !isPassengerInfoWindow;
    passengerInfoWindow = isPassengerInfoWindow == true ? 200 : 0;
    update();
  }

  @override
  void onInit() {
    // Get the passenger location from the arguments.
    passengerLocation = Get.arguments['passengerLocation'];
    duration = Get.arguments['Duration'];
    passengerId = Get.arguments['passengerId'];
    driverId = Get.arguments['driverId'];
    distance = Get.arguments['Distance'];
    name = Get.arguments['name'];
    phone = Get.arguments['phone'];
    walletChecked = Get.arguments['WalletChecked'];
    tokenPassenger = Get.arguments['tokenPassenger'];
    direction = Get.arguments['direction'];
    durationToPassenger = Get.arguments['DurationToPassenger'];
    rideId = Get.arguments['rideId'];
    durationOfRideValue = Get.arguments['durationOfRideValue'];
    paymentAmount = Get.arguments['paymentAmount'];
    paymentMethod = Get.arguments['paymentMethod'];
    String lat = Get.find<LocationController>().myLocation.latitude.toString();
    String lng = Get.find<LocationController>().myLocation.longitude.toString();
    String origin = '$lat,$lng';
    // Set the origin and destination coordinates for the Google Maps directions request.
    getMap(origin, passengerLocation);
    addCustomCarIcon();
    // updateMarker();
    startTimerToShowPassengerInfoWindowFromDriver();
    // checkIsDriverNearPassenger();
    super.onInit();
  }
}
