import 'dart:convert';
import 'dart:io';
import 'package:sefer_driver/constant/api_key.dart';
import 'package:sefer_driver/controller/home/captin/home_captain_controller.dart';
import 'package:sefer_driver/views/widgets/error_snakbar.dart';
import 'package:sefer_driver/views/widgets/mydialoug.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:http/http.dart' as http;
import 'package:sefer_driver/views/widgets/elevated_btn.dart';

import '../../constant/box_name.dart';
import '../../constant/colors.dart';
import '../../constant/style.dart';
import '../../env/env.dart';
import '../../main.dart';
import '../../print.dart';
import '../../views/auth/captin/criminal_documents_page.dart';
import '../../views/home/Captin/home_captain/home_captin.dart';
import '../../views/home/Captin/orderCaptin/order_speed_request.dart';
import '../../views/home/Captin/orderCaptin/order_request_page.dart';
import '../../views/home/Captin/orderCaptin/vip_order_page.dart';
import '../auth/google_sign.dart';
import '../functions/encrypt_decrypt.dart';
import '../functions/face_detect.dart';
import 'access_token.dart';
import 'local_notification.dart';

class FirebaseMessagesController extends GetxController {
  final fcmToken = FirebaseMessaging.instance;

  List<String> tokens = [];
  List dataTokens = [];
  late String driverID;
  late String driverToken;
  NotificationSettings? notificationSettings;
  NotificationController notificationController =
      Get.put(NotificationController());
  Future<void> getNotificationSettings() async {
    // Get the current notification settings
    NotificationSettings? notificationSettings =
        await FirebaseMessaging.instance.getNotificationSettings();
    'Notification authorization status: ${notificationSettings.authorizationStatus}';

    // Call the update function if needed
    update();
  }

  Future<void> requestFirebaseMessagingPermission() async {
    FirebaseMessaging messaging = FirebaseMessaging.instance;

    // Check if the platform is Android
    if (Platform.isAndroid) {
      // Request permission for Android
      await messaging.requestPermission();
    } else if (Platform.isIOS) {
      // Request permission for iOS
      NotificationSettings settings = await messaging.requestPermission(
        alert: true,
        announcement: true,
        badge: true,
        carPlay: true,
        criticalAlert: true,
        provisional: false,
        sound: true,
      );
      messaging.setForegroundNotificationPresentationOptions(
          alert: true, badge: true, sound: true);
    }
  }

  Future getToken() async {
    fcmToken.getToken().then((token) {
      Log.print('token: ${token}');
      box.write(BoxName.tokenDriver, (token!));
    });

    FirebaseMessaging.onMessage.listen((RemoteMessage message) {
      // If the app is in the background or terminated, show a system tray message
      RemoteNotification? notification = message.notification;
      AndroidNotification? android = notification?.android;
      // if (notification != null && android != null) {

      if (message.data.isNotEmpty && message.notification != null) {
        fireBaseTitles(message);
      }
      if (message.data.isNotEmpty && message.notification != null) {
        fireBaseTitles(message);
      }
    });
    FirebaseMessaging.onBackgroundMessage((RemoteMessage message) async {});

    FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
      if (message.data.isNotEmpty && message.notification != null) {
        fireBaseTitles(message);
      }
    });
  }

  Future<void> fireBaseTitles(RemoteMessage message) async {
    if (message.notification!.title! == 'Order') {
      if (Platform.isAndroid) {
        notificationController.showNotification(
            message.notification!.title.toString(),
            message.notification!.body.toString(),
            'tone1',
            '');
      }
      // await FirebaseMessagesController().showOverlayNotification(message);
      var myListString = message.data['DriverList'];
      // var points = message.data['PolylineJson'];

      var myList = jsonDecode(myListString) as List<dynamic>;
      // var myPoints = jsonDecode(points) as List<dynamic>;
      driverToken = myList[14].toString();
      // This is for location using and uploading status
      Get.put(HomeCaptainController()).changeRideId();
      update();
      Get.to(() => OrderRequestPage(), arguments: {
        // Get.to(() => OrderRequestPage(), arguments: {
        'myListString': myListString,
        'DriverList': myList,
        // 'PolylineJson': myPoints,
        'body': message.notification!.body
      });
    } else if (message.notification!.title == 'OrderVIP') {
      var myListString = message.data['DriverList'];

      var myList = jsonDecode(myListString) as List<dynamic>;

      // driverToken = myList[10].toString();
      if (Platform.isAndroid) {
        notificationController.showNotification(
            'OrderVIP'.tr, 'OrderVIP'.tr, 'order', '');
      }
      Get.to(VipOrderPage(), arguments: {
        'myListString': myListString,
        'DriverList': myList,
        // 'PolylineJson': myPoints,
        'body': message.notification!.body
      });
    } else if (message.notification!.title == 'Cancel Trip'.tr) {
      if (Platform.isAndroid) {
        notificationController.showNotification(
            'Cancel Trip'.tr, 'Passenger Cancel Trip'.tr, 'cancel', '');
      }
      cancelTripDialog();
    } else if (message.notification!.title == 'VIP Order') {
      var myListString = message.data['DriverList'];
      var driverList = jsonDecode(myListString) as List<dynamic>;
      if (Platform.isAndroid) {
        notificationController.showNotification(
            'VIP Order'.tr, '', 'order', '');
      }
      MyDialog().getDialog('VIP Order'.tr, 'midTitle', () {
        sendNotificationToPassengerToken(
            'VIP Order Accepted'.tr,
            'The driver accepted your trip'.tr,
            driverList[0],
            [driverList[1]],
            'order');
      });

      // Get.to(const VipOrderPage());
    } else if (message.notification!.title == 'message From passenger') {
      if (Platform.isAndroid) {
        notificationController.showNotification(
            'message From passenger'.tr, ''.tr, 'ding', '');
      }
      MyDialog().getDialog(
          'message From passenger'.tr, message.notification!.body!, () {
        Get.back();
      });
    } else if (message.notification!.title == 'Cancel') {
      if (Platform.isAndroid) {
        notificationController.showNotification(
            'Cancel'.tr, ''.tr, 'cancel', '');
      }
      MyDialog().getDialog(
          'Passenger Cancel Trip'.tr,
          'Trip Cancelled. The cost of the trip will be added to your wallet.'
              .tr, () {
        box.write(BoxName.rideStatus, 'Cancel');
        Log.print('rideStatus from 184 : ${box.read(BoxName.rideStatus)}');
        Get.offAll(HomeCaptain());
      });
      // cancelTripDialog1();
    } else if (message.notification!.title! == 'token change') {
      // notificationController
      //     .showNotification('token change'.tr, 'token change', 'cancel');
      // GoogleSignInHelper.signOut();
      GoogleSignInHelper.signOut();
    } else if (message.notification!.title! == 'face detect') {
      if (Platform.isAndroid) {
        notificationController.showNotification(
            'face detect'.tr, ''.tr, 'tone2', '');
      }
      String result0 = await faceDetector();
      // Handle the result here, e.g., show a dialog or update the UI
      var result = jsonDecode(result0);
      MyDialogContent().getDialog(
        'Face Detection Result'.tr,
        Text(
          result['similar'].toString() == 'true'
              ? 'similar'.tr
              : 'not similar'.tr,
          style: AppStyle.title,
        ),
        () {
          Get.back();
        },
      );

      update();
    } else if (message.notification!.title! == 'Hi ,I will go now') {
      if (Platform.isAndroid) {
        notificationController.showNotification(
            'Passenger come to you'.tr, 'Hi ,I will go now'.tr, 'tone2', '');
      }
      update();
    } else if (message.notification!.title! == 'Call Income'.tr) {
      try {
        var myListString = message.data['passengerList'];
        var driverList = jsonDecode(myListString) as List<dynamic>;
        // if (Platform.isAndroid) {
        if (Platform.isAndroid) {
          notificationController.showNotification('Call Income'.tr,
              message.notification!.body!, 'iphone_ringtone', '');
        }
        // }
        // Assuming GetMaterialApp is initialized and context is valid for navigation
        // Get.to(() => PassengerCallPage(
        //       channelName: driverList[1].toString(),
        //       token: driverList[0].toString(),
        //       remoteID: driverList[2].toString(),
        //     ));
      } catch (e) {}
    } else if (message.notification!.title! ==
        'Call Income from Passenger'.tr) {
      try {
        var myListString = message.data['passengerList'];
        var driverList = jsonDecode(myListString) as List<dynamic>;
        // if (Platform.isAndroid) {
        if (Platform.isAndroid) {
          notificationController.showNotification('Call Income'.tr,
              message.notification!.body!, 'iphone_ringtone', '');
        }
        // }
        // Assuming GetMaterialApp is initialized and context is valid for navigation
        // Get.to(() => CallPage(
        //     // channelName: driverList[1].toString(),
        //     // token: driverList[0].toString(),
        //     // remoteID: driverList[2].toString(),
        //     ));
      } catch (e) {}
    } else if (message.notification!.title! ==
        "Criminal Document Required".tr) {
      if (Platform.isAndroid) {
        notificationController.showNotification("Criminal Document Required".tr,
            message.notification!.body!, 'tone2', '');
      }
      MyDialog().getDialog(
          "Criminal Document Required".tr, 'You should have upload it .'.tr,
          () {
        Get.to(() => const CriminalDocumemtPage());
      });
      Get.to(() => const CriminalDocumemtPage());
    } else if (message.notification!.title! == 'Call End'.tr) {
      try {
        var myListString = message.data['passengerList'];
        var driverList = jsonDecode(myListString) as List<dynamic>;
        if (Platform.isAndroid) {
          notificationController.showNotification(
              'Call End'.tr, message.notification!.body!, 'tone2', '');
        }
        // Assuming GetMaterialApp is initialized and context is valid for navigation
        // Get.off(const CallPage());
      } catch (e) {}
    } else if (message.notification!.title! == 'Order Applied'.tr) {
      mySnackbarSuccess("The order has been accepted by another driver.".tr);
    } else if (message.notification!.title! == 'Order') {
      if (Platform.isAndroid) {
        notificationController.showNotification(
            message.notification!.title.toString(),
            message.notification!.body.toString(),
            'order',
            '');
      }
      var myListString = message.data['DriverList'];
      // var points = message.data['PolylineJson'];

      var myList = jsonDecode(myListString) as List<dynamic>;
      // var myPoints = jsonDecode(points) as List<dynamic>;
      driverToken = myList[14].toString();
      Get.put(HomeCaptainController()).changeRideId();
      update();
      Get.to(() => OrderSpeedRequest(), arguments: {
        'myListString': myListString,
        'DriverList': myList,
        // 'PolylineJson': myPoints,
        'body': message.notification!.body
      });
    } else if (message.notification!.title! == 'Order Applied'.tr) {
      if (Platform.isAndroid) {
        notificationController.showNotification(
            'The order Accepted by another Driver'.tr,
            'We regret to inform you that another driver has accepted this order.'
                .tr,
            'order',
            '');
      }
    }
  }

  SnackbarController driverAppliedTripSnakBar() {
    return Get.snackbar(
      'Driver Applied the Ride for You'.tr,
      '',
      colorText: AppColor.greenColor,
      duration: const Duration(seconds: 3),
      snackPosition: SnackPosition.TOP,
      titleText: Text(
        'Applied'.tr,
        style: const TextStyle(color: AppColor.redColor),
      ),
      messageText: Text(
        'Driver Applied the Ride for You'.tr,
        style: AppStyle.title,
      ),
      icon: const Icon(Icons.approval),
      shouldIconPulse: true,
      margin: const EdgeInsets.all(16),
      padding: const EdgeInsets.all(16),
    );
  }

  Future<dynamic> cancelTripDialog() {
    return Get.defaultDialog(
        barrierDismissible: false,
        title: 'Passenger Cancel Trip'.tr,
        middleText: '',
        confirm: MyElevatedButton(
            title: 'Ok'.tr,
            onPressed: () {
              box.write(BoxName.rideStatus, 'Cancel');
              box.write(BoxName.statusDriverLocation, 'off');
              Log.print(
                  'rideStatus from 347 : ${box.read(BoxName.rideStatus)}');
              Get.offAll(HomeCaptain());
            }));
  }

  Future<dynamic> cancelTripDialog1() {
    return Get.defaultDialog(
        barrierDismissible: false,
        title: 'Passenger Cancel Trip'.tr,
        middleText:
            'Trip Cancelled. The cost of the trip will be added to your wallet.'
                .tr,
        confirm: MyElevatedButton(
            title: 'Ok'.tr,
            onPressed: () {
              box.write(BoxName.rideStatus, 'Cancel');
              Log.print(
                  'rideStatus from 364 : ${box.read(BoxName.rideStatus)}');
              Get.offAll(HomeCaptain());
            }));
  }

  // Future<dynamic> driverArrivePassengerDialoge() {
  //   return Get.defaultDialog(
  //       barrierDismissible: false,
  //       title: 'Hi ,I Arrive your site'.tr,
  //       middleText: 'Please go to Car Driver'.tr,
  //       confirm: MyElevatedButton(
  //           title: 'Ok I will go now.'.tr,
  //           onPressed: () {
  //             FirebaseMessagesController().sendNotificationToPassengerToken(
  //                 'Hi ,I will go now'.tr,
  //                 'I will go now'.tr,
  //                 Get.find<MapDriverController>().driverToken, []);
  //             Get.find<MapPassengerController>()
  //                 .startTimerDriverWaitPassenger5Minute();

  //             Get.back();
  //           }));
  // }

  Future<dynamic> passengerDialog(String message) {
    return Get.defaultDialog(
        barrierDismissible: false,
        title: 'message From passenger'.tr,
        titleStyle: AppStyle.title,
        middleTextStyle: AppStyle.title,
        middleText: message.tr,
        confirm: MyElevatedButton(
            title: 'Ok'.tr,
            onPressed: () {
              //   FirebaseMessagesController().sendNotificationToPassengerToken(
              //       'Hi ,I will go now'.tr,
              //       'I will go now'.tr,
              //       Get.find<MapPassengerController>().driverToken, []);
              //   Get.find<MapPassengerController>()
              //       .startTimerDriverWaitPassenger5Minute();

              Get.back();
            }));
  }

  late String serviceAccountKeyJson;
  @override
  Future<void> onInit() async {
    super.onInit();
    try {
      var encryptedKey = Env.privateKeyFCM;
      // Log.print('encryptedKey: ${encryptedKey}');
      serviceAccountKeyJson =
          EncryptionHelper.instance.decryptData(encryptedKey);
      // Log.print('serviceAccountKeyJson: ${serviceAccountKeyJson}');
    } catch (e) {
      print('🔴 Error decrypting FCM key: $e');
    }
  }

  void sendNotificationAll(String title, body, tone) async {
    // Get the token you want to subtract.
    String token = box.read(BoxName.tokenFCM);
    tokens = box.read(BoxName.tokens);
    // Subtract the token from the list of tokens.
    tokens.remove(token);

    // Save the list of tokens back to the box.
    // box.write(BoxName.tokens, tokens);
    tokens = box.read(BoxName.tokens);
    for (var i = 0; i < tokens.length; i++) {
      if (serviceAccountKeyJson.isEmpty) {
        print("🔴 Error: Service Account Key is empty");
        return;
      }
      // Initialize AccessTokenManager
      final accessTokenManager = AccessTokenManager(serviceAccountKeyJson);

      // Obtain an OAuth 2.0 access token
      final accessToken = await accessTokenManager.getAccessToken();
      // Log.print('accessToken: ${accessToken}');

      // Send the notification
      final response = await http
          .post(
            Uri.parse(
                'https://fcm.googleapis.com/v1/projects/ride-b1bd8/messages:send'),
            headers: <String, String>{
              'Content-Type': 'application/json',
              'Authorization': 'Bearer $accessToken',
            },
            body: jsonEncode({
              'message': {
                'token': token,
                'notification': {
                  'title': title,
                  'body': body,
                },
                // 'data': {
                //   'DriverList': jsonEncode(data),
                // },
                'android': {
                  'priority': 'high', // Set priority to high
                  'notification': {
                    'sound': tone,
                  },
                },
                'apns': {
                  'headers': {
                    'apns-priority': '10', // Set APNs priority to 10
                  },
                  'payload': {
                    'aps': {
                      'sound': tone,
                    },
                  },
                },
              },
            }),
          )
          .whenComplete(() {})
          .catchError((e) {});
    }
  }

  void sendNotificationToPassengerToken(
      String title, body, token, List<String> map, String tone,
      {int retryCount = 2}) async {
    try {
      if (serviceAccountKeyJson.isEmpty) {
        print("🔴 Error: Service Account Key is empty");
        return;
      }
      // Initialize AccessTokenManager
      final accessTokenManager = AccessTokenManager(serviceAccountKeyJson);

      // Obtain an OAuth 2.0 access token
      final accessToken = await accessTokenManager.getAccessToken();
      // Log.print('accessToken: ${accessToken}');

      // Send the notification
      final response = await http.post(
        Uri.parse(
            'https://fcm.googleapis.com/v1/projects/ride-b1bd8/messages:send'),
        headers: <String, String>{
          'Content-Type': 'application/json',
          'Authorization': 'Bearer $accessToken',
        },
        body: jsonEncode({
          'message': {
            'token': token,
            'notification': {
              'title': title,
              'body': body,
            },
            'data': {
              'passengerList': jsonEncode(map),
            },
            'android': {
              'priority': 'high', // Set priority to high
              'notification': {
                'sound': tone,
              },
            },
            'apns': {
              'headers': {
                'apns-priority': '10', // Set APNs priority to 10
              },
              'payload': {
                'aps': {
                  'sound': tone,
                },
              },
            },
          },
        }),
      );

      if (response.statusCode == 200) {
        print(
            'Notification sent successfully. Status code: ${response.statusCode}');
        print('Response body: ${response.body}');
      } else {
        print(
            'Failed to send notification. Status code: ${response.statusCode}');

        print('Response body: ${response.body}');
        if (retryCount > 0) {
          print('Retrying... Attempts remaining: $retryCount');
          await Future.delayed(
              const Duration(seconds: 2)); // Optional delay before retrying
          return sendNotificationToPassengerToken(title, body, token, map, tone,
              retryCount: retryCount - 1);
        }
      }
    } catch (e) {
      print('Error sending notification: $e');
      if (retryCount > 0) {
        print('Retrying... Attempts remaining: $retryCount');
        await Future.delayed(
            const Duration(seconds: 2)); // Optional delay before retrying
        return sendNotificationToPassengerToken(title, body, token, map, tone,
            retryCount: retryCount - 1);
      }
    }
  }

  void sendNotificationToPassengerTokenCALL(
      String title, body, token, List<String> map, String tone,
      {int retryCount = 2}) async {
    try {
      if (serviceAccountKeyJson.isEmpty) {
        print("🔴 Error: Service Account Key is empty");
        return;
      }
      // Initialize AccessTokenManager
      final accessTokenManager = AccessTokenManager(serviceAccountKeyJson);

      // Obtain an OAuth 2.0 access token
      final accessToken = await accessTokenManager.getAccessToken();
      // Log.print('accessToken: ${accessToken}');

      // Send the notification
      final response = await http.post(
        Uri.parse(
            'https://fcm.googleapis.com/v1/projects/ride-b1bd8/messages:send'),
        headers: <String, String>{
          'Content-Type': 'application/json',
          'Authorization': 'Bearer $accessToken',
        },
        body: jsonEncode({
          'message': {
            'token': token,
            'notification': {
              'title': title,
              'body': body,
            },
            'data': {
              'passengerList': jsonEncode(map),
            },
            'android': {
              'priority': 'high', // Set priority to high
              'notification': {
                'sound': tone,
              },
            },
            'apns': {
              'headers': {
                'apns-priority': '10', // Set APNs priority to 10
              },
              'payload': {
                'aps': {
                  'sound': tone,
                },
              },
            },
          },
        }),
      );

      if (response.statusCode == 200) {
        print(
            'Notification sent successfully. Status code: ${response.statusCode}');
        print('Response body: ${response.body}');
      } else {
        print(
            'Failed to send notification. Status code: ${response.statusCode}');

        print('Response body: ${response.body}');
        if (retryCount > 0) {
          print('Retrying... Attempts remaining: $retryCount');
          await Future.delayed(
              const Duration(seconds: 2)); // Optional delay before retrying
          return sendNotificationToPassengerTokenCALL(
              title, body, token, map, tone,
              retryCount: retryCount - 1);
        }
      }
    } catch (e) {
      print('Error sending notification: $e');
      if (retryCount > 0) {
        print('Retrying... Attempts remaining: $retryCount');
        await Future.delayed(
            const Duration(seconds: 2)); // Optional delay before retrying
        return sendNotificationToPassengerTokenCALL(
            title, body, token, map, tone,
            retryCount: retryCount - 1);
      }
    }
  }

  Future<void> sendNotificationToDriverMAP(
      String title, String body, String token, List<String> data, String tone,
      {int retryCount = 2}) async {
    try {
      if (serviceAccountKeyJson.isEmpty) {
        print("🔴 Error: Service Account Key is empty");
        return;
      }

      // Initialize AccessTokenManager
      final accessTokenManager = AccessTokenManager(serviceAccountKeyJson);
      Log.print(
          'accessTokenManager: ${accessTokenManager.serviceAccountJsonKey}');

      // Obtain an OAuth 2.0 access token
      final accessToken = await accessTokenManager.getAccessToken();
      // Log.print('accessToken: ${accessToken}');

      // Send the notification
      final response = await http.post(
        Uri.parse(
            'https://fcm.googleapis.com/v1/projects/intaleq-d48a7/messages:send'),
        headers: <String, String>{
          'Content-Type': 'application/json',
          'Authorization': 'Bearer $accessToken',
        },
        body: jsonEncode({
          'message': {
            'token': token,
            'notification': {
              'title': title,
              'body': body,
            },
            'data': {
              'DriverList': jsonEncode(data),
            },
            'android': {
              'priority': 'high', // Set priority to high
              'notification': {
                'sound': tone,
              },
            },
            'apns': {
              'headers': {
                'apns-priority': '10', // Set APNs priority to 10
              },
              'payload': {
                'aps': {
                  'sound': tone,
                },
              },
            },
          },
        }),
      );

      if (response.statusCode == 200) {
        print(
            'Notification sent successfully. Status code: ${response.statusCode}');
        // print('Response token: ${token}');
      } else {
        print(
            'Failed to send notification. Status code: ${response.statusCode}');
        print('Response body: ${response.body}');
        if (retryCount > 0) {
          print('Retrying... Attempts remaining: $retryCount');
          await Future.delayed(
              Duration(seconds: 2)); // Optional delay before retrying
          return sendNotificationToDriverMAP(title, body, token, data, tone,
              retryCount: retryCount - 1);
        }
      }
    } catch (e) {
      print('Error sending notification: $e');
      if (retryCount > 0) {
        print('Retrying... Attempts remaining: $retryCount');
        await Future.delayed(
            Duration(seconds: 2)); // Optional delay before retrying
        return sendNotificationToDriverMAP(title, body, token, data, tone,
            retryCount: retryCount - 1);
      }
    }
  }

  Future<void> removeInvalidToken(String token) async {
    // Remove token from your database/storage
    // This prevents future attempts to send to invalid tokens
    print('Removing invalid token from database: $token');
    // Your database cleanup logic here
  }
}

class OverlayContent extends StatelessWidget {
  final String title;
  final String body;

  OverlayContent(this.title, this.body);

  @override
  Widget build(BuildContext context) {
    return Material(
      child: Container(
        padding: const EdgeInsets.all(16.0),
        color: Colors.white,
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Text(
              title,
              style: const TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
            ),
            const SizedBox(height: 8.0),
            Text(
              body,
              style: const TextStyle(fontSize: 16),
            ),
          ],
        ),
      ),
    );
  }
}
