import 'dart:async';
import 'dart:convert';
import 'dart:io' show Platform;

import 'package:diplomaticquarterapp/analytics/google-analytics.dart';
import 'package:diplomaticquarterapp/config/config.dart';
import 'package:diplomaticquarterapp/config/shared_pref_kay.dart';
import 'package:diplomaticquarterapp/core/service/medical/vital_sign_service.dart';
import 'package:diplomaticquarterapp/core/service/packages_offers/PackagesOffersServices.dart';
import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart';
import 'package:diplomaticquarterapp/models/Appointments/toDoCountProviderModel.dart';
import 'package:diplomaticquarterapp/pages/appUpdatePage/app_update_page.dart';
import 'package:diplomaticquarterapp/services/authentication/auth_provider.dart';
import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart';
import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart';
import 'package:diplomaticquarterapp/uitl/utils.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:provider/provider.dart';

import '../../../locator.dart';
import '../../../routes.dart';
import '../AuthenticatedUserObject.dart';

AppSharedPreferences sharedPref = new AppSharedPreferences();

///Example
///await BaseAppClient.post('',
///       onSuccess: (dynamic response, int statusCode) {},
///       onFailure: (String error, int statusCode) {},
///   body: Map();
///
AuthenticatedUserObject authenticatedUserObject = locator<AuthenticatedUserObject>();
VitalSignService _vitalSignService = locator<VitalSignService>();

class BaseAppClient {
  final _analytics = locator<GAnalytics>();

  post(String endPoint,
      {Map<String, dynamic> body,
      Function(dynamic response, int statusCode) onSuccess,
      Function(String error, int statusCode) onFailure,
      bool isAllowAny = false,
      bool isExternal = false,
      bool isRCService = false,
      bool bypassConnectionCheck = false}) async {
    String url;
    if (isExternal) {
      url = endPoint;
    } else {
      if (isRCService)
        url = RC_BASE_URL + endPoint;
      else
        url = BASE_URL + endPoint;
    }
    try {
      var pharmacyToken = await sharedPref.getString(PHARMACY_AUTORZIE_TOKEN);
      var user = await sharedPref.getObject(USER_PROFILE);
      Map<String, String> headers = {'Content-Type': 'application/json', 'Accept': 'application/json'};
      if (!isExternal) {
        String token = await sharedPref.getString(TOKEN);
        var languageID = await sharedPref.getStringWithDefaultValue(APP_LANGUAGE, 'ar');
        if (endPoint == SEND_ACTIVATION_CODE) {
          languageID = 'en';
        }
        if (body.containsKey('SetupID')) {
          body['SetupID'] = body.containsKey('SetupID')
              ? body['SetupID'] != null
                  ? body['SetupID']
                  : SETUP_ID
              : SETUP_ID;
        }

        body['VersionID'] = VERSION_ID;
        body['Channel'] = CHANNEL;
        body['LanguageID'] = (languageID == 'ar' ? 1 : 2);

        body['IPAdress'] = IP_ADDRESS;
        body['generalid'] = GENERAL_ID;

        body['Latitude'] = await AppSharedPreferences().getDouble(USER_LAT);
        body['Longitude'] = await AppSharedPreferences().getDouble(USER_LONG);

        if (body.containsKey('isDentalAllowedBackend')) {
          body['isDentalAllowedBackend'] = body.containsKey('isDentalAllowedBackend')
              ? body['isDentalAllowedBackend'] != null
                  ? body['isDentalAllowedBackend']
                  : IS_DENTAL_ALLOWED_BACKEND
              : IS_DENTAL_ALLOWED_BACKEND;
        }

        body['DeviceTypeID'] = Platform.isIOS ? 1 : 2;

        if (!body.containsKey('IsPublicRequest')) {
          // if (!body.containsKey('PatientType')) {
          if (user != null && user['PatientType'] != null) {
            body['PatientType'] = user['PatientType'];
          } else {
            body['PatientType'] = PATIENT_TYPE;
          }
          // }

          // body['PatientType'] = body.containsKey('PatientType')
          //     ? body['PatientType'] != null
          //         ? body['PatientType']
          //         : user['PatientType'] != null
          //             ? user['PatientType']
          //             : PATIENT_TYPE
          //     : PATIENT_TYPE;

          // if (!body.containsKey('PatientTypeID')) {
          if (user != null && user['PatientType'] != null) {
            body['PatientTypeID'] = user['PatientType'];
          } else {
            body['PatientType'] = PATIENT_TYPE_ID;
          }
          // }

          // body['PatientTypeID'] = body.containsKey('PatientTypeID')
          //     ? body['PatientTypeID'] != null
          //         ? body['PatientTypeID']
          //         : user['PatientType'] != null
          //             ? user['PatientType']
          //             : PATIENT_TYPE_ID
          //     : PATIENT_TYPE_ID;

          if (user != null) {
            body['TokenID'] = body['TokenID'] != null ? body['TokenID'] : token;
            body['PatientID'] = body['PatientID'] != null ? body['PatientID'] : user['PatientID'];

            body['PatientOutSA'] = body.containsKey('PatientOutSA')
                ? body['PatientOutSA'] != null
                    ? body['PatientOutSA']
                    : user['OutSA']
                : user['OutSA'];
            body['SessionID'] = getSessionId(body['TokenID']); //getSe

            headers = {
              'Content-Type': 'application/json',
              'Accept': 'application/json',
              'Authorization': pharmacyToken,
              'Mobilenumber': user != null ? Utils.getPhoneNumberWithoutZero(user['MobileNumber'].toString()) : "",
              'Statictoken': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9',
              'Username': user['PatientID'].toString(),
            };
          }
        }
      }

      // body['IdentificationNo'] = 1023854217;
      // body['MobileNo'] = "531940021";
      // body['PatientID'] = 2001273; //3844083
      // body['TokenID'] = "@dm!n";

      // Patient ID: 3027574
      // Mobile no.: 0502303285
      // ID: 119116817

      body.removeWhere((key, value) => key == null || value == null);

      if (AppGlobal.isNetworkDebugEnabled) {
        print("URL : $url");
        final jsonBody = json.encode(body);
        print(jsonBody);
      }

      if (await Utils.checkConnection(bypassConnectionCheck: bypassConnectionCheck)) {
        final response = await http.post(Uri.parse(url.trim()), body: json.encode(body), headers: headers);
        final int statusCode = response.statusCode;
        if (statusCode < 200 || statusCode >= 400 || json == null) {
          onFailure('Error While Fetching data', statusCode);
          logApiEndpointError(endPoint, 'Error While Fetching data', statusCode);
        } else {
          var decoded = utf8.decode(response.bodyBytes);
          var parsed = json.decode(utf8.decode(response.bodyBytes));

          // print("Response: $parsed");

          if (isAllowAny) {
            onSuccess(parsed, statusCode);
          } else {
            if (parsed['Response_Message'] != null) {
              onSuccess(parsed, statusCode);
            } else {
              if (parsed['ErrorType'] == 4) {
                navigateToAppUpdate(AppGlobal.context, parsed['ErrorEndUserMessage']);
                logApiEndpointError(endPoint, parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode);
              }
              if (parsed['ErrorType'] == 2) {
                await logout();
                logApiEndpointError(endPoint, "session logged out", statusCode);
              }
              if (isAllowAny) {
                onSuccess(parsed, statusCode);
              } else if (parsed['IsAuthenticated'] == null) {
                if (parsed['isSMSSent'] == true) {
                  onSuccess(parsed, statusCode);
                } else if (parsed['MessageStatus'] == 1) {
                  onSuccess(parsed, statusCode);
                } else if (parsed['Result'] == 'OK') {
                  onSuccess(parsed, statusCode);
                } else {
                  // if (parsed != null) {
                  //   onSuccess(parsed, statusCode);
                  // } else {
                  onFailure(parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode);
                  logApiEndpointError(endPoint, parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode);
                  // logout();
                  // }
                }
              } else if (parsed['MessageStatus'] == 1 || parsed['SMSLoginRequired'] == true) {
                onSuccess(parsed, statusCode);
              } else if (parsed['MessageStatus'] == 2 && parsed['IsAuthenticated']) {
                if (parsed['SameClinicApptList'] != null) {
                  onSuccess(parsed, statusCode);
                } else {
                  if (parsed['message'] == null && parsed['ErrorEndUserMessage'] == null) {
                    if (parsed['ErrorSearchMsg'] == null) {
                      onFailure("Server Error found with no available message", statusCode);
                      logApiEndpointError(endPoint, "Server Error found with no available message", statusCode);
                    } else {
                      onFailure(parsed['ErrorSearchMsg'], statusCode);
                      logApiEndpointError(endPoint, parsed['ErrorSearchMsg'], statusCode);
                    }
                  } else {
                    onFailure(parsed['message'] ?? parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode);
                    logApiEndpointError(endPoint, parsed['message'] ?? parsed['message'], statusCode);
                  }
                }
              }
              // else if (!parsed['IsAuthenticated']) {
              //   await logout();
              // }
              else {
                if (parsed['SameClinicApptList'] != null) {
                  onSuccess(parsed, statusCode);
                } else {
                  if (parsed['message'] != null) {
                    onFailure(parsed['message'] ?? parsed['message'], statusCode);
                    logApiEndpointError(endPoint, parsed['message'] ?? parsed['message'], statusCode);
                  } else {
                    onFailure(parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode);
                    logApiEndpointError(endPoint, parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode);
                  }
                }
              }
            }
          }
        }
      } else {
        onFailure('Please Check The Internet Connection', -1);
        _analytics.errorTracking.log("internet_connectivity", error: "no internet available");
      }
    } catch (e) {
      print(e);
      onFailure(e.toString(), -1);
      _analytics.errorTracking.log(endPoint, error: "api exception: $e");
    }
  }

  postPharmacy(String endPoint,
      {Map<String, dynamic> body, Function(dynamic response, int statusCode) onSuccess, Function(String error, int statusCode) onFailure, bool isAllowAny = false, bool isExternal = false}) async {
    var token = await sharedPref.getString(PHARMACY_AUTORZIE_TOKEN);
    var user = await sharedPref.getObject(USER_PROFILE);
    String url;
    if (isExternal) {
      url = endPoint;
    } else {
      url = PHARMACY_BASE_URL + endPoint;
    }
    try {
      //Map profile = await sharedPref.getObj(DOCTOR_PROFILE);
      var pharmacyToken = await sharedPref.getString(PHARMACY_AUTORZIE_TOKEN);
      var user = await sharedPref.getObject(USER_PROFILE);
      Map<String, String> headers = {
        'Content-Type': 'application/json',
        'Accept': 'application/json',
        'Authorization': pharmacyToken ?? '',
        'Mobilenumber': user != null ? Utils.getPhoneNumberWithoutZero(user['MobileNumber'].toString()) : "",
        'Statictoken': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9',
        'Username': user != null ? user['PatientID'].toString() : "",
      };
      if (!isExternal) {
        String token = await sharedPref.getString(TOKEN);
        var languageID = await sharedPref.getStringWithDefaultValue(APP_LANGUAGE, 'ar');

        // if (body.containsKey('SetupID')) {
        //   body['SetupID'] = body.containsKey('SetupID')
        //       ? body['SetupID'] != null
        //           ? body['SetupID']
        //           : SETUP_ID
        //       : SETUP_ID;
        // }
        //
        // body['VersionID'] = VERSION_ID;
        // body['Channel'] = CHANNEL;
        // body['LanguageID'] = languageID == 'ar' ? 1 : 2;
        //
        // body['IPAdress'] = IP_ADDRESS;
        // body['generalid'] = GENERAL_ID;
        // body['PatientOutSA'] = body.containsKey('PatientOutSA')
        //     ? body['PatientOutSA'] != null
        //         ? body['PatientOutSA']
        //         : PATIENT_OUT_SA
        //     : PATIENT_OUT_SA;
        //
        // if (body.containsKey('isDentalAllowedBackend')) {
        //   body['isDentalAllowedBackend'] = body.containsKey('isDentalAllowedBackend')
        //       ? body['isDentalAllowedBackend'] != null
        //           ? body['isDentalAllowedBackend']
        //           : IS_DENTAL_ALLOWED_BACKEND
        //       : IS_DENTAL_ALLOWED_BACKEND;
        // }
        //
        // body['DeviceTypeID'] = Platform.isAndroid ? 1 : 2;
        //
        // if (!body.containsKey('IsPublicRequest')) {
        //   body['PatientType'] = body.containsKey('PatientType')
        //       ? body['PatientType'] != null
        //           ? body['PatientType']
        //           : user['PatientType'] != null
        //               ? user['PatientType']
        //               : PATIENT_TYPE
        //       : PATIENT_TYPE;
        //
        //   body['PatientTypeID'] = body.containsKey('PatientTypeID')
        //       ? body['PatientTypeID'] != null
        //           ? body['PatientTypeID']
        //           : user['PatientType'] != null
        //               ? user['PatientType']
        //               : PATIENT_TYPE_ID
        //       : PATIENT_TYPE_ID;
        //   if (user != null) {
        //     body['TokenID'] = token;
        //     body['PatientID'] = body['PatientID'] != null ? body['PatientID'] : user['PatientID'];
        //     body['PatientOutSA'] = user['OutSA'];
        //     body['SessionID'] = SESSION_ID; //getSe
        //   }
        // }
      }

      print("URL : $url");
      print("Body : ${json.encode(body)}");
      print("Headers : ${json.encode(headers)}");

      if (await Utils.checkConnection()) {
        final response = await http.post(Uri.parse(url.trim()), body: json.encode(body), headers: headers);
        final int statusCode = response.statusCode;
        // print("statusCode :$statusCode");
        if (statusCode < 200 || statusCode >= 400 || json == null) {
          onFailure('Error While Fetching data', statusCode);
          logApiEndpointError(endPoint, 'Error While Fetching data', statusCode);
        } else {
          // var parsed = json.decode(response.body.toString());
          var parsed = json.decode(utf8.decode(response.bodyBytes));
          if (parsed['Response_Message'] != null) {
            onSuccess(parsed, statusCode);
          } else {
            if (parsed['ErrorType'] == 4) {
              navigateToAppUpdate(AppGlobal.context, parsed['ErrorEndUserMessage']);
              logApiEndpointError(endPoint, parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode);
            }
            if (isAllowAny) {
              onSuccess(parsed, statusCode);
            } else if (parsed['IsAuthenticated'] == null) {
              if (parsed['isSMSSent'] == true) {
                onSuccess(parsed, statusCode);
              } else if (parsed['MessageStatus'] == 1) {
                onSuccess(parsed, statusCode);
              } else if (parsed['Result'] == 'OK') {
                onSuccess(parsed, statusCode);
              } else {
                if (parsed != null) {
                  onSuccess(parsed, statusCode);
                } else {
                  onFailure(parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode);
                  logApiEndpointError(endPoint, parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode);
                  logApiEndpointError(endPoint, 'session logged out', statusCode);
                  logout();
                }
              }
            } else if (parsed['MessageStatus'] == 1 || parsed['SMSLoginRequired'] == true) {
              onSuccess(parsed, statusCode);
            } else if (parsed['MessageStatus'] == 2 && parsed['IsAuthenticated']) {
              if (parsed['SameClinicApptList'] != null) {
                onSuccess(parsed, statusCode);
              } else {
                if (parsed['message'] == null && parsed['ErrorEndUserMessage'] == null) {
                  if (parsed['ErrorSearchMsg'] == null) {
                    onFailure("Server Error found with no available message", statusCode);
                    logApiEndpointError(endPoint, "Server Error found with no available message", statusCode);
                  } else {
                    onFailure(parsed['ErrorSearchMsg'], statusCode);
                    logApiEndpointError(endPoint, parsed['ErrorSearchMsg'] ?? parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode);
                  }
                } else {
                  onFailure(parsed['message'] ?? parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode);
                  logApiEndpointError(endPoint, parsed['message'] ?? parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode);
                }
              }
            } else if (!parsed['IsAuthenticated']) {
              await logout();

              //helpers.showErrorToast('Your session expired Please login agian');
            } else {
              if (parsed['SameClinicApptList'] != null) {
                onSuccess(parsed, statusCode);
              } else {
                if (parsed['message'] != null) {
                  onFailure(parsed['message'] ?? parsed['message'], statusCode);
                  logApiEndpointError(endPoint, parsed['message'] ?? parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode);
                } else {
                  onFailure(parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode);
                  logApiEndpointError(endPoint, parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode);
                }
              }
            }
          }
        }
      } else {
        onFailure('Please Check The Internet Connection', -1);
        _analytics.errorTracking.log("internet_connectivity", error: "no internet available");
      }
    } catch (e) {
      print(e);
      onFailure(e.toString(), -1);
      _analytics.errorTracking.log(endPoint, error: "api exception: $e");
    }
  }

  Future navigateToAppUpdate(context, String text) async {
    Navigator.pushAndRemoveUntil(
      context,
      MaterialPageRoute(builder: (context) => AppUpdatePage(appUpdateText: text)),
      (Route<dynamic> route) => false,
    );
  }

  get(String endPoint,
      {Function(dynamic response, int statusCode) onSuccess,
      Function(String error, int statusCode) onFailure,
      Map<String, dynamic> queryParams,
      bool isExternal = false,
      bool isRCService = false}) async {
    String url;
    if (isExternal) {
      url = endPoint;
    } else {
      if (isRCService)
        url = RC_BASE_URL + endPoint;
      else
        url = BASE_URL + endPoint;
    }
    if (queryParams != null) {
      String queryString = Uri(queryParameters: queryParams).query;
      url += '?' + queryString;
    }

    debugPrint("URL : $url");
    // print("Body : ${json.encode(body)}");

    if (await Utils.checkConnection()) {
      final response = await http.get(
        Uri.parse(url.trim()),
        headers: {'Content-Type': 'application/json', 'Accept': 'application/json'},
      );
      final int statusCode = response.statusCode;
      // print("statusCode :$statusCode");

      if (statusCode < 200 || statusCode >= 400 || json == null) {
        onFailure('Error While Fetching data', statusCode);
        logApiEndpointError(endPoint, 'Error While Fetching data', statusCode);
      } else {
        var parsed = json.decode(utf8.decode(response.bodyBytes));
        onSuccess(parsed, statusCode);
      }
    } else {
      onFailure('Please Check The Internet Connection', -1);
      _analytics.errorTracking.log("internet_connectivity", error: "no internet available");
    }
  }

  getPharmacy(String endPoint,
      {Function(dynamic response, int statusCode) onSuccess,
      Function(String error, int statusCode) onFailure,
      bool isAllowAny = false,
      bool isExternal = false,
      Map<String, dynamic> queryParams}) async {
    var token = await sharedPref.getString(PHARMACY_AUTORZIE_TOKEN);
    var user = await sharedPref.getObject(USER_PROFILE);

    String url;
    if (isExternal) {
      url = endPoint;
    } else {
      url = PHARMACY_BASE_URL + endPoint;
    }
    if (queryParams != null) {
      String queryString = Uri(queryParameters: queryParams).query;
      url += '?' + queryString;
    }

    print("URL : $url");
    var ss = json.encode(queryParams);

    if (await Utils.checkConnection()) {
      final response = await http.get(Uri.parse(url.trim()), headers: {
        'Content-Type': 'text/html; charset=utf-8',
        'Accept': 'application/json',
        'Authorization': token ?? '',
        'Mobilenumber': user != null ? Utils.getPhoneNumberWithoutZero(user['MobileNumber'].toString()) : "",
        'Statictoken': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9',
        'Username': user != null ? user['PatientID'].toString() : "",
        // 'Host': "mdlaboratories.com",
      });
      final int statusCode = response.statusCode;
      // print("statusCode :$statusCode");

      if (statusCode < 200 || statusCode >= 400 || json == null) {
        if (statusCode == 401) {
          onFailure(TranslationBase.of(AppGlobal.context).pharmacyRelogin, statusCode);
          logApiEndpointError(endPoint, TranslationBase.of(AppGlobal.context).pharmacyRelogin, statusCode);
          Navigator.of(AppGlobal.context).pushNamed(HOME);
        } else {
          var bodyUtf = json.decode(utf8.decode(response.bodyBytes));
          // print(bodyUtf);
          onFailure(bodyUtf['error']['ErrorEndUserMsg'], statusCode);
          logApiEndpointError(endPoint, bodyUtf['error']['ErrorEndUserMsg'], statusCode);
        }
      } else {
        // var parsed = json.decode(response.body.toString());
        var bodyUtf = json.decode(utf8.decode(response.bodyBytes));
        onSuccess(bodyUtf, statusCode);
      }
    } else {
      onFailure('Please Check The Internet Connection', -1);
      _analytics.errorTracking.log("internet_connectivity", error: "no internet available");
    }
  }

  simplePost(
    String fullUrl, {
    Map<dynamic, dynamic> body,
    Map<String, String> headers,
    Function(dynamic response, int statusCode) onSuccess,
    Function(String error, int statusCode) onFailure,
  }) async {
    String url = fullUrl;
    // print("URL Query String: $url");
    // print("body: $body");

    if (await Utils.checkConnection()) {
      headers.addAll({'Content-Type': 'application/json', 'Accept': 'application/json'});
      final response = await http.post(
        Uri.parse(url.trim()),
        body: json.encode(body),
        headers: headers,
      );
      final int statusCode = response.statusCode;
      // print("statusCode :$statusCode");
      if (await handleUnauthorized(statusCode, forUrl: fullUrl)) simplePost(fullUrl, onFailure: onFailure, onSuccess: onSuccess, body: body, headers: headers);

      // print(response.body.toString());

      if (statusCode < 200 || statusCode >= 400 || json == null) {
        onFailure('Error While Fetching data', statusCode);
        logApiFullUrlError(fullUrl, 'Error While Fetching data', statusCode);
      } else {
        onSuccess(response.body.toString(), statusCode);
      }
    } else {
      onFailure('Please Check The Internet Connection', -1);
      _analytics.errorTracking.log("internet_connectivity", error: "no internet available");
    }
  }

  simpleGet(String fullUrl,
      {Function(dynamic response, int statusCode) onSuccess, Function(String error, int statusCode) onFailure, Map<String, dynamic> queryParams, Map<String, String> headers}) async {
    headers = headers ?? {};
    String url = fullUrl;

    var haveParams = (queryParams != null);
    if (haveParams) {
      String queryString = Uri(queryParameters: queryParams).query;
      url += '?' + queryString;
      // print("URL Query String: $url");
    }

    if (await Utils.checkConnection()) {
      headers.addAll({'Content-Type': 'application/json', 'Accept': 'application/json'});
      final response = await http.get(
        Uri.parse(url.trim()),
        headers: headers,
      );

      final int statusCode = response.statusCode;
      // print("statusCode :$statusCode");
      if (await handleUnauthorized(statusCode, forUrl: fullUrl)) simpleGet(fullUrl, onFailure: onFailure, onSuccess: onSuccess, headers: headers, queryParams: queryParams);

      if (statusCode < 200 || statusCode >= 400 || json == null) {
        onFailure('Error While Fetching data', statusCode);
        logApiFullUrlError(fullUrl, 'Error While Fetching data', statusCode);
      } else {
        onSuccess(response.body.toString(), statusCode);
      }
    } else {
      onFailure('Please Check The Internet Connection', -1);
      _analytics.errorTracking.log("internet_connectivity", error: "no internet available");
    }
  }

  simplePut(String fullUrl, {Map<String, dynamic> body, Map<String, String> headers, Function(dynamic response, int statusCode) onSuccess, Function(String error, int statusCode) onFailure}) async {
    String url = fullUrl;
    // print("URL Query String: $url");

    if (await Utils.checkConnection()) {
      headers.addAll({'Content-Type': 'application/json', 'Accept': 'application/json'});
      final response = await http.put(
        Uri.parse(url.trim()),
        body: json.encode(body),
        headers: headers,
      );

      final int statusCode = response.statusCode;
      // print("statusCode :$statusCode");
      if (await handleUnauthorized(statusCode, forUrl: fullUrl)) simplePut(fullUrl, onFailure: onFailure, onSuccess: onSuccess, headers: headers, body: body);

      if (statusCode < 200 || statusCode >= 400 || json == null) {
        onFailure('Error While Fetching data', statusCode);
        logApiFullUrlError(fullUrl, 'Error While Fetching data', statusCode);
      } else {
        onSuccess(response.body.toString(), statusCode);
      }
    } else {
      onFailure('Please Check The Internet Connection', -1);
      _analytics.errorTracking.log("internet_connectivity", error: "no internet available");
    }
  }

  simpleDelete(String fullUrl,
      {Function(dynamic response, int statusCode) onSuccess, Function(String error, int statusCode) onFailure, Map<String, String> queryParams, Map<String, String> headers}) async {
    String url = fullUrl;
    // print("URL Query String: $url");

    var haveParams = (queryParams != null);
    if (haveParams) {
      String queryString = Uri(queryParameters: queryParams).query;
      url += '?' + queryString;
      // print("URL Query String: $url");
    }

    if (await Utils.checkConnection()) {
      headers.addAll({'Content-Type': 'application/json', 'Accept': 'application/json'});
      final response = await http.delete(
        Uri.parse(url.trim()),
        headers: headers,
      );

      final int statusCode = response.statusCode;
      // print("statusCode :$statusCode");
      if (await handleUnauthorized(statusCode, forUrl: fullUrl)) simpleDelete(fullUrl, onFailure: onFailure, onSuccess: onSuccess, queryParams: queryParams, headers: headers);

      if (statusCode < 200 || statusCode >= 400 || json == null) {
        onFailure('Error While Fetching data', statusCode);
        logApiFullUrlError(fullUrl, 'Error While Fetching data', statusCode);
      } else {
        onSuccess(response.body.toString(), statusCode);
      }
    } else {
      onFailure('Please Check The Internet Connection', -1);
      _analytics.errorTracking.log("internet_connectivity", error: "no internet available");
    }
  }

  Future<bool> handleUnauthorized(int statusCode, {String forUrl}) async {
    if (forUrl.startsWith(EXA_CART_API_BASE_URL) && statusCode == 401) {
      final token = await generatePackagesToken();
      packagesAuthHeader['Authorization'] = 'Bearer $token';
      return token != null && (token is String);
    }
    return false;
  }

  logout() async {
    await sharedPref.remove(LOGIN_TOKEN_ID);
    await sharedPref.remove(PHARMACY_CUSTOMER_ID);
    await authenticatedUserObject.getUser();
    Provider.of<ProjectViewModel>(AppGlobal.context, listen: false).isLogin = false;
    var model = Provider.of<ToDoCountProviderModel>(AppGlobal.context, listen: false);
    _vitalSignService.weightKg = "";
    _vitalSignService.heightCm = "";
    model.setState(0, false, null);
    Navigator.of(AppGlobal.context).pushReplacementNamed(HOME);
  }

  String getSessionId(String id) {
    ///return id.replaceAll(RegExp('/[^\w\s]/'), '');
    return id.replaceAll(RegExp('/[^a-zA-Z]'), '');
  }

  static defaultHttpParameters() async {
    String token = await sharedPref.getString(TOKEN);
    var languageID = await sharedPref.getStringWithDefaultValue(APP_LANGUAGE, 'ar');
    var user = await sharedPref.getObject(USER_PROFILE);
    var params = {};
    if (user != null) {
      params['TokenID'] = token;
      params['PatientID'] = user['PatientID'];
      params['PatientOutSA'] = user['OutSA'];
      params['SessionID'] = SESSION_ID; //getSessionId(token);
    }

    params['IPAdress'] = IP_ADDRESS;
    params['generalid'] = GENERAL_ID;
    params['VersionID'] = VERSION_ID;
    params['Channel'] = CHANNEL;
    params['LanguageID'] = languageID == 'ar' ? 1 : 2;

    return params;
  }

  pharmacyPost(String endPoint,
      {Map<String, dynamic> body, Function(dynamic response, int statusCode) onSuccess, Function(String error, int statusCode) onFailure, bool isAllowAny = false, bool isExternal = false}) async {
    var token = await sharedPref.getString(PHARMACY_AUTORZIE_TOKEN);
    var user = await sharedPref.getObject(USER_PROFILE);
    String url;
    if (isExternal) {
      url = endPoint;
    } else {
      url = BASE_PHARMACY_URL + endPoint;
    }
    try {
      if (isExternal) {
        String token = await sharedPref.getString(TOKEN);
        var languageID = await sharedPref.getStringWithDefaultValue(APP_LANGUAGE, 'ar');
        var user = await sharedPref.getObject(USER_PROFILE);
        if (body.containsKey('SetupID')) {
          body['SetupID'] = body.containsKey('SetupID')
              ? body['SetupID'] != null
                  ? body['SetupID']
                  : SETUP_ID
              : SETUP_ID;
        }

        body['VersionID'] = VERSION_ID;
        body['Channel'] = CHANNEL;
        body['LanguageID'] = languageID == 'ar' ? 1 : 2;

        body['IPAdress'] = IP_ADDRESS;
        body['generalid'] = GENERAL_ID;
        body['PatientOutSA'] = body.containsKey('PatientOutSA')
            ? body['PatientOutSA'] != null
                ? body['PatientOutSA']
                : user['OutSA']
            : user['OutSA'];

        if (body.containsKey('isDentalAllowedBackend')) {
          body['isDentalAllowedBackend'] = body.containsKey('isDentalAllowedBackend')
              ? body['isDentalAllowedBackend'] != null
                  ? body['isDentalAllowedBackend']
                  : IS_DENTAL_ALLOWED_BACKEND
              : IS_DENTAL_ALLOWED_BACKEND;
        }

        body['DeviceTypeID'] = Platform.isAndroid ? 1 : 2;

        if (!body.containsKey('IsPublicRequest')) {
          body['PatientType'] = body.containsKey('PatientType')
              ? body['PatientType'] != null
                  ? body['PatientType']
                  : user['PatientType'] != null
                      ? user['PatientType']
                      : user['PatientType']
              : user['PatientType'];

          body['PatientTypeID'] = body.containsKey('PatientTypeID')
              ? body['PatientTypeID'] != null
                  ? body['PatientTypeID']
                  : user['PatientType'] != null
                      ? user['PatientType']
                      : user['PatientType']
              : user['PatientType'];
          if (user != null) {
            body['TokenID'] = token;
            body['PatientID'] = body['PatientID'] != null ? body['PatientID'] : user['PatientID'];
            body['PatientOutSA'] = user['OutSA'];
            // body['SessionID'] = SESSION_ID; //getSessionId(token);
          }
        }
      }

      // print("URL : $url");
      // print("Body : ${json.encode(body)}");
      var ss = json.encode(body);

      if (await Utils.checkConnection()) {
        final response = await http.post(Uri.parse(url.trim()), body: json.encode(body), headers: {
          'Content-Type': 'application/json',
          'Accept': 'application/json',
          'Authorization': token ?? '',
          'Mobilenumber': user != null ? Utils.getPhoneNumberWithoutZero(user['MobileNumber'].toString()) : "",
          'Statictoken': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9',
          'Username': user != null ? user['PatientID'].toString() : "",
        });
        final int statusCode = response.statusCode;
        // print("statusCode :$statusCode");
        if (statusCode < 200 || statusCode >= 400 || json == null) {
          var parsed = json.decode(utf8.decode(response.bodyBytes));
          onFailure(parsed['error']['ErrorEndUserMsgN'] ?? 'Error While Fetching data', statusCode);
          logApiEndpointError(endPoint, parsed['error']['ErrorEndUserMsgN'] ?? 'Error While Fetching data', statusCode);
        } else {
          // var parsed = json.decode(response.body.toString());
          var parsed = json.decode(utf8.decode(response.bodyBytes));
          if (parsed['Response_Message'] != null) {
            onSuccess(parsed, statusCode);
          } else {
            if (parsed['ErrorType'] == 4) {
              navigateToAppUpdate(AppGlobal.context, parsed['ErrorEndUserMessage']);
            }
            if (isAllowAny) {
              onSuccess(parsed, statusCode);
            } else if (parsed['IsAuthenticated'] == null) {
              if (parsed['isSMSSent'] == true) {
                onSuccess(parsed, statusCode);
              } else if (parsed['MessageStatus'] == 1) {
                onSuccess(parsed, statusCode);
              } else if (parsed['Result'] == 'OK') {
                onSuccess(parsed, statusCode);
              } else {
                if (parsed != null) {
                  onSuccess(parsed, statusCode);
                } else {
                  onFailure(parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode);
                  logApiEndpointError(endPoint, parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode);
                  logout();
                }
              }
            } else if (parsed['MessageStatus'] == 1 || parsed['SMSLoginRequired'] == true) {
              onSuccess(parsed, statusCode);
            } else if (parsed['MessageStatus'] == 2 && parsed['IsAuthenticated']) {
              if (parsed['message'] == null && parsed['ErrorEndUserMessage'] == null) {
                if (parsed['ErrorSearchMsg'] == null) {
                  onFailure("Server Error found with no available message", statusCode);
                  logApiEndpointError(endPoint, "Server Error found with no available message", statusCode);
                } else {
                  onFailure(parsed['ErrorSearchMsg'], statusCode);
                  logApiEndpointError(endPoint, parsed['ErrorSearchMsg'], statusCode);
                }
              } else {
                onFailure(parsed['message'] ?? parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode);
                logApiEndpointError(endPoint, parsed['message'] ?? parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode);
              }
            } else if (!parsed['IsAuthenticated']) {
              await logout();

              //helpers.showErrorToast('Your session expired Please login agian');
            } else {
              if (parsed['SameClinicApptList'] != null) {
                onSuccess(parsed, statusCode);
              } else {
                if (parsed['message'] != null) {
                  onFailure(parsed['message'] ?? parsed['message'], statusCode);
                  logApiEndpointError(endPoint, parsed['message'] ?? parsed['message'], statusCode);
                } else {
                  onFailure(parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode);
                  logApiEndpointError(endPoint, parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode);
                }
              }
            }
          }
        }
      } else {
        onFailure('Please Check The Internet Connection', -1);
        _analytics.errorTracking.log("internet_connectivity", error: "no internet available");
      }
    } catch (e) {
      print(e);
      onFailure(e.toString(), -1);
      logApiEndpointError(endPoint, e.toString(), -1);
    }
  }

  Future<String> generatePackagesToken() async {
    var url = EXA_CART_API_BASE_URL + PACKAGES_TOKEN;
    var body = {
      "api_client": {"client_id": "a4ab6be4-424f-4836-b032-46caed88e184", "client_secret": "3c1a3e07-4a40-4510-9fb0-ee5f0a72752c"}
    };
    String token;
    final completer = Completer();
    simplePost(url, body: body, headers: {}, onSuccess: (dynamic stringResponse, int statusCode) {
      if (statusCode == 200) {
        var jsonResponse = json.decode(stringResponse);
        token = jsonResponse['auth_token'];
        completer.complete();
      }
    }, onFailure: (String error, int statusCode) {
      completer.complete();
      logApiFullUrlError(url, error, statusCode);
    });
    await completer.future;
    return token;
  }

  logApiFullUrlError(String fullUrl, error, code) {
    final endpoint = Uri.parse(fullUrl).pathSegments.last;
    logApiEndpointError(endpoint, error, code);
  }

  logApiEndpointError(String endPoint, error, code) {
    _analytics.errorTracking.log(endPoint, error: error);
  }
}
