/* Created by Nitesh Kumar on 05/28/24 */

import 'dart:async';
import 'dart:io' show Platform;
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:dio/dio.dart';
import 'package:exide_crr/data/app_env.dart';
import 'package:exide_crr/data/remote_config_helper.dart';
import 'package:exide_crr/preferences/app_shared_preferences.dart';
import 'package:exide_crr/services/service_locator.dart';
import 'package:exide_crr/utils/helper_class.dart';
import 'package:exide_crr/utils/miscellaneous.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:url_launcher/url_launcher.dart';

class BaseController extends GetxController with WidgetsBindingObserver {
  final tag = "BaseController";

  late PreferenceHelper preferenceHelper;
  final RemoteConfigHelper remoteConfigHelper = locator.get<RemoteConfigHelper>();

  RxBool isGeneralConfigLoading = false.obs;
  Completer<void> generalConfigFetchCompleter = Completer<void>();

  ///verifyOtp
  RxString generatedOtp="".obs;
  //todo-Fetch the phone number from welcome screen
  RxString userPhoneNumber="919945215727".obs;



  String encryptedSseId = "";
  String userName = "";
  String fullName = "";
  String userDesignation = "";
  String userEmail = "";
  String empMobileNo = "";
  String empWorkLocation = "";
  String assetUrl = "";
  String userSelectedLob = "";
  String userSelectedChannel = "";
  String forgetPasswordUrl = "";
  bool feedbackType = false;
  String apiEncryptionKey = "";
  String clientId = "";
  String clientSecretKey = "";
  List<String> channels = [];
  String sseId = "";
  String deviceTokenString = "";
  String lookerDashboardUrl = "";

  RxString currentVersion = "".obs;
  String appVersion = "";

  // --- considering default user type id as zero ---
  int userTypeId = 0;

  String apiEncryptionSecretKeyBIP = "";
  RxList newFeatureList = [].obs;

  RxString docsId = "".obs;

  String buildNumber = "";
  String buildVersion = "";

  RxBool isNoInternet = false.obs;

  //Feedback
  // RxString userName = ''.obs;
  RxString number = ''.obs;
  RxString fromEmail = ''.obs;
  RxString toEmail = ''.obs;
  RxString initialMail = ''.obs;
  RxString description = ''.obs;
  RxBool isButtonEnabled = false.obs;
  RxBool isButtonLoading = false.obs;
  RxBool isFeedbackError = false.obs;

  bool isValidName = false;
  bool isValidEmail = false;
  bool isValidNumber = false;
  // RxBool isSuccess = false.obs;
  RxString responseText = ''.obs;
  RxBool isFeedbackFormLocked = false.obs;
  RxInt currentCharacterCount = 0.obs;

  RxList agencySMTag = [].obs;
  RxList agencyHMTag = [].obs;
  RxBool fetchAllDisplayCardConfig = false.obs;
  bool disableNudge = false;

  bool forceUpdate = false;

  // bool forceUpdateIos = false;
  String androidVersionName = "";
  String androidVersionCode = "";
  String androidMinVersionName = "";
  String androidMinVersionCode = "";
  String iosVersionName = "";
  String iosVersionCode = "";
  String iosMinVersionName = "";
  String iosMinVersionCode = "";

  // RxBool isFirstTimeLoggedInBool = true.obs;
  RxBool isLoggedIn = false.obs;
  RxString companyName = "".obs;
  String userId = "";
  RxInt selectedSideBarIndex = 0.obs;
  GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();

  RxBool isTierPriceUpdated = false.obs;
  // RxInt tabIndex = 0.obs;

  RxInt tabIndex = 0.obs;
  RxList<String> userPermissionList = <String>[].obs;

  // RxList<Map<String, dynamic>> userPermissionList = <Map<String, dynamic>>[].obs;
  Dio dio = Dio();
  String orderId = "";
  Stream<bool> getTierUpdatedValue() async* {
    yield isTierPriceUpdated.value;
  }

  List<String> listOfAppBarName = [
    "Dashboard",
    "Pricing Management",
    "Order Management",
    "Promotion Management",
    "Bulk Product Update",
    "User & Company Management",
    "About Us",
  ];

  //////////////
  RxList<Map<String, dynamic>> categoryList = <Map<String, dynamic>>[].obs;
  RxMap<String, dynamic> categoryValue = <String, dynamic>{}.obs;
  RxBool isCategoryLoading = false.obs;
  //////////////
  RxList<Map<String, dynamic>> subCategoryList = <Map<String, dynamic>>[].obs;
  RxMap<String, dynamic> subCategoryValue = <String, dynamic>{}.obs;
  RxBool isSubCategoryLoading = false.obs;

  TabController? tabController;

  @override
  void onInit() async {
    super.onInit();
    WidgetsBinding.instance.addObserver(this);
    Miscellaneous.logMessage(tag, " ------ BaseController init -----");
    getAppVersion();
    getPackageInfo();
    getFireStoreInstance(AppEnvironment.appEnvironmentSetup.name);
  }

  void getPackageInfo() async {
    PackageInfo packageInfo = await PackageInfo.fromPlatform();
    buildNumber = packageInfo.buildNumber;
    buildVersion = packageInfo.version;
    Miscellaneous.logMessage(tag, "Build number $buildNumber");
  }

  String getClientId() {
    clientId = remoteConfigHelper.getClientId();
    return clientId;
  }

  String getClientSecretKey() {
    clientSecretKey = remoteConfigHelper.getClientSecretKey();
    return clientSecretKey;
  }

  Future<void> updateApp() async {
    String urlStr = "";
    if (Platform.isAndroid) {
      urlStr = remoteConfigHelper.getApkUpdateUrl();
    } else {
      urlStr = remoteConfigHelper.getIOSUpdateUrl();
    }

    if (urlStr.isNotEmpty) {
      Uri url = Uri.parse(urlStr.toString());
      if (!await launchUrl(url,
          mode: LaunchMode.externalNonBrowserApplication)) {
        throw 'Could not launch $url';
      }
    }
  }

  Future<bool> checkUpdateStatus() async {
    PackageInfo packageInfo = await PackageInfo.fromPlatform();

    try {
      String packageVersion = packageInfo.version;
      if (packageVersion.contains('-')) {
        packageVersion = packageVersion.split('-').first;
      }
      int? localVersion = int.tryParse(packageVersion.replaceAll(".", ""));

      if (localVersion == null) {
        return false;
      }
      String buildNumberStr = packageInfo.buildNumber;
      if (buildNumberStr.contains('.')) {
        buildNumberStr = buildNumberStr.replaceAll(".", "");
      }
      Miscellaneous.logMessage(tag, 'version :: $localVersion');
      Miscellaneous.logMessage(tag, 'build :: $buildNumberStr');
      androidVersionName = remoteConfigHelper.getAndroidVersion();
      androidVersionCode = remoteConfigHelper.getAndroidBuild();
      androidMinVersionName = remoteConfigHelper.getAndroidMinVersion();
      androidMinVersionCode = remoteConfigHelper.getAndroidMinBuild();
      Miscellaneous.logMessage(
          tag, 'androidVersionName :: $androidVersionName');
      Miscellaneous.logMessage(
          tag, 'androidVersionCode :: $androidVersionCode');
      iosVersionName = remoteConfigHelper.getIOSVersion();
      iosVersionCode = remoteConfigHelper.getIOSBuild();
      iosMinVersionName = remoteConfigHelper.getIOSMinVersion();
      iosMinVersionCode = remoteConfigHelper.getIOSMinBuild();

      int localBuildNumber = int.parse(buildNumberStr);
      if (iosVersionCode.contains('.')) {
        iosVersionCode = iosVersionCode.replaceAll(".", "");
      }
      if (iosMinVersionCode.contains('.')) {
        iosMinVersionCode = iosMinVersionCode.replaceAll(".", "");
      }

      if (Platform.isAndroid) {
        if (androidVersionName.isEmpty || androidVersionCode.isEmpty) {
          return false;
        }
        if (localVersion <
                int.parse(androidMinVersionName.replaceAll(".", "")) ||
            localBuildNumber < int.parse(androidMinVersionCode)) {
          forceUpdate = true;
          return true;
        }
        if (localVersion < int.parse(androidVersionName.replaceAll(".", "")) ||
            localBuildNumber < int.parse(androidVersionCode)) {
          return true;
        }
      }

      if (Platform.isIOS) {
        if (iosVersionName.isEmpty || iosVersionCode.isEmpty) {
          return false;
        }
        if (iosMinVersionName.isNotEmpty &&
            iosMinVersionCode.isNotEmpty &&
            (localVersion < int.parse(iosMinVersionName.replaceAll(".", "")) ||
                localBuildNumber < int.parse(iosMinVersionCode))) {
          forceUpdate = true;

          return true;
        }
        if (localVersion < int.parse(iosVersionName.replaceAll(".", "")) ||
            localBuildNumber < int.parse(iosVersionCode)) {
          return true;
        }
      }
    } catch (st) {
      Miscellaneous.logMessage(tag, st);
    }
    return false;
  }

  @override
  void onClose() {
    super.onClose();
    WidgetsBinding.instance.removeObserver(this);
    // Dispose the package when it is no longer needed
    // dataPackage.dispose();
  }

  Future<bool> getDecryptedUserDetails({
    required String encryptedDetails,
    required String encryptedToken,
    required String encryptedId,
    isTokenRequired = true,
    bool isStoreEncryptedDetails = false,
  }) async {
    try {
      if (isTokenRequired == true) {
        // GetEncryptedSSEIDRequestModel requestModel =
        //     GetEncryptedSSEIDRequestModel(
        //   {"userInput": encryptedDetails},
        // );

        // loggedUserDetails =
        //     await HttpServiceImpl.getHttpServiceImpl(isApigee: true)
        //         .getDecryptedUserDetails(encryptedToken, requestModel);
      } else {
        try {
          // dynamic decryptedUserDetails =
          //     await decryptUserDetails(encryptedData: encryptedDetails);
          // Miscellaneous.logMessage("Decrypt Data", decryptedUserDetails);
          // Map<String, dynamic> userDetail = json.decode(decryptedUserDetails);
          // UserDetails userDetails = UserDetails.fromJson(userDetail);

          // loggedUserDetails = UserDetailsResponseModel(
          //     message: "",
          //     isSuccess: true,
          //     responseCode: SUCCESS,
          //     userDetails: userDetails);
        } catch (e) {
          Miscellaneous.logMessage(tag,
              'An error occurred while getting decrypted user details: $e');
          return false;
        }
      }
      return false;
    } catch (e, st) {
      Miscellaneous.logMessage(tag, "getting error $st");
      return false;
    }
  }

  void setEncryptedUserValues({required String encryptedSSID}) {
    encryptedSseId = encryptedSSID;
  }

  void discardDetails() {
    resetData();
    Get.until((route) => !Get.isDialogOpen!);
  }

  void resetData() {
    number.value = "";
    fromEmail.value = "";
    description.value = "";
    isButtonEnabled.value = false;
    isFeedbackFormLocked.value = false;
  }

  void dataValidation() {
    String pattern = r'^[\w-]+(\.[\w-]+)*@([\w-]+\.)+[a-zA-Z]{2,7}$';
    RegExp regex = RegExp(pattern);
    bool invalidRegex = regex.hasMatch(fromEmail.value);
    bool invalidToRegex = regex.hasMatch(toEmail.value);
    if (feedbackType == true) {
      if (fromEmail.isNotEmpty &&
          invalidRegex &&
          toEmail.isNotEmpty &&
          invalidToRegex &&
          description.isNotEmpty &&
          number.isNotEmpty &&
          number.value.length == 10) {
        isButtonEnabled.value = true;
      } else {
        isButtonEnabled.value = false;
      }
    } else {
      if (description.isNotEmpty &&
          number.isNotEmpty &&
          number.value.length == 10) {
        isButtonEnabled.value = true;
      } else {
        isButtonEnabled.value = false;
      }
    }
  }

  bool isEmptyCheck() {
    return (number.value == '' &&
        fromEmail.value == '' &&
        toEmail.value == '' &&
        description.value == '');
  }

  String emailTemplate({required String desc, required String phNo}) {
    return "<html><p>Hi Team,<br><br>There has been feedback raised by the Manager $fullName through the 1UP.SALES application. Please find below for the details of the same.<br><br><b>From Details:</b><br><br><b>Employee ID - </b> $sseId<br><b> Manager Name - </b> $fullName<br><b>Contact No - </b>$phNo<br><b>Email ID - </b>$userEmail<br><br><b>Feedback Raised:</b><br> $desc <br><br>Regards,<br>Product Team<br>1Up.Sales</p></html> ";
  }

  String? validateEmail(String? value, String? type) {
    if (type == "email" || type == "toEmail" || type == "fromEmail") {
      String pattern = r'^[\w-]+(\.[\w-]+)*@([\w-]+\.)+[a-zA-Z]{2,7}$';
      RegExp regex = RegExp(pattern);
      if (value == null || value.isEmpty || !regex.hasMatch(value)) {
        return 'Enter a valid email address';
      } else {
        if (type == "fromEmail") {
          fromEmail = value.obs;
          return null;
        } else if (type == "toEmail") {
          toEmail = value.obs;
          return null;
        } else {
          initialMail = value.obs;
          return null;
        }
      }
    } else if (type == "mobile") {
      String pattern = r'(^(?:[+0]9)?[0-9]{10,12}$)';
      RegExp regExp = RegExp(pattern);
      if (value != null && value.isEmpty) {
        return 'Please enter mobile number';
      } else if (!regExp.hasMatch(value!)) {
        return 'Please enter valid mobile number';
      } else if (value.length == 10) {
        int repeated = 0;
        String first = value[0];
        for (var element in value.characters) {
          element == first ? repeated++ : repeated = 0;
        }
        if (repeated >= 9) {
          return 'Please enter valid mobile number';
        } else {
          number = value.obs;
          return null;
        }
      } else {
        return null;
      }
    } else if (type == "name") {
      if (value == null || value.isEmpty /*|| !regExp.hasMatch(value!)*/) {
        return 'Please enter proper name';
      } else {
        return null;
      }
    } else {
      return null;
    }
  }

  Future<void> resetDB() async {
    // OvalLiteRepository.instance.clearDeepDiveLocalData();
    await PreferenceHelper.clearUserPreferenceData();
  }

  void logoutUser() {
    // Future.delayed(
    //   const Duration(milliseconds: 250),
    //   () async {
    //     await resetDB();
    //     Get.offAllNamed(
    //       RoutesName.loginScreen,
    //     );
    //   },
    // );
  }

  Future<String> encryptUserDetails({required String encryptingData}) async {
    String encryptionKey = await getEncryptionSecretKey();
    return Miscellaneous.setEncryptData(
        encryptingData: encryptingData, encryptionKey: encryptionKey);
  }

  Future<String> getEncryptionSecretKey() async {
    if (apiEncryptionKey == "") {
      apiEncryptionKey = await remoteConfigHelper.getApiEncryptionKey();
    }
    Miscellaneous.logMessage(tag, apiEncryptionKey);
    return apiEncryptionKey;
  }

  Future<String> decryptUserDetails({required String encryptedData}) async {
    String encryptKey = await getEncryptionSecretKey();
    return Miscellaneous.getDecryptSecureData(
        encryptedData: encryptedData, encryptionKey: encryptKey);
  }

  void getAppVersion() async {
    if (appVersion.isEmpty) {
      PackageInfo packageInfo = await PackageInfo.fromPlatform();
      Miscellaneous.logMessage(tag, packageInfo.version);
      Miscellaneous.logMessage(tag, packageInfo.buildNumber);
      String env = AppEnvironment.appEnvironmentSetup == Environment.test
          ? "test"
          : AppEnvironment.appEnvironmentSetup == Environment.dev
              ? "dev"
              : AppEnvironment.appEnvironmentSetup == Environment.uat
                  ? "uat"
                  : "rc";
      String version = "${packageInfo.version}-$env${packageInfo.buildNumber}";
      appVersion = version;
    }
  }

  /// switch fireStore DB based on [environment]
  FirebaseFirestore getFireStoreInstance(String environment) {
    switch (environment) {
      case 'uat':
        return FirebaseFirestore.instanceFor(
            app: Firebase.app(), databaseURL: 'uat-b2b-database');
      default:
        return FirebaseFirestore.instance;
    }
  }



  getTokenData() async {
    String token = await PreferenceHelper.getPreferenceData(PreferenceHelper.accessToken) ?? "";

    HelperClass.printWrapped("Token=========+$token");
  }
}