import 'package:diplomaticquarterapp/config/config.dart';
import 'package:diplomaticquarterapp/config/shared_pref_kay.dart';
import 'package:diplomaticquarterapp/core/service/AuthenticatedUserObject.dart';
import 'package:diplomaticquarterapp/core/service/client/base_app_client.dart';
import 'package:diplomaticquarterapp/models/Authentication/authenticated_user.dart';
import 'package:diplomaticquarterapp/models/Authentication/check_activation_code_request.dart';
import 'package:diplomaticquarterapp/models/Authentication/check_activation_code_request_register.dart';
import 'package:diplomaticquarterapp/models/Authentication/check_activation_code_response.dart';
import 'package:diplomaticquarterapp/models/Authentication/check_paitent_authentication_req.dart';
import 'package:diplomaticquarterapp/models/Authentication/check_user_status_req.dart';
import 'package:diplomaticquarterapp/models/Authentication/checkpatient_for_registration.dart';
import 'package:diplomaticquarterapp/models/Authentication/insert_device_imei_request.dart';
import 'package:diplomaticquarterapp/models/Authentication/register_user_requet.dart';
import 'package:diplomaticquarterapp/models/Authentication/registered_authenticated_user_req.dart';
import 'package:diplomaticquarterapp/models/Authentication/select_device_imei_res.dart';
import 'package:diplomaticquarterapp/models/Request.dart';
import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart';
import 'package:flutter/cupertino.dart';
import 'package:intl/intl.dart';
import '../../locator.dart';

// SharedPreferences sharedPref = new SharedPreferences();
enum APP_STATUS { LOADING, UNAUTHENTICATED, AUTHENTICATED }

AppSharedPreferences sharedPref = new AppSharedPreferences();
AppGlobal appGlobal = new AppGlobal();

const String INSERT_DEVICE_IMEI = 'Services/Patients.svc/REST/Patient_INSERTDeviceIMEI';
const String SELECT_DEVICE_IMEI = 'Services/Patients.svc/REST/Patient_SELECTDeviceIMEIbyIMEI';
const String CHECK_PATIENT_AUTH = 'Services/Authentication.svc/REST/CheckPatientAuthentication';
const GET_MOBILE_INFO = 'Services/Authentication.svc/REST/GetMobileLoginInfo';
const SEND_ACTIVATION_CODE = 'Services/Authentication.svc/REST/SendActivationCodebyOTPNotificationType';

const SEND_ACTIVATION_CODE_REGISTER = 'Services/Authentication.svc/REST/SendActivationCodebyOTPNotificationTypeForRegistration';
const CHECK_ACTIVATION_CODE = 'Services/Authentication.svc/REST/CheckActivationCode';
const CHECK_ACTIVATION_CODE_REGISTER = 'Services/Authentication.svc/REST/CheckActivationCodeForRegistration';

const FORGOT_PASSWORD = 'Services/Authentication.svc/REST/CheckActivationCodeForSendFileNo';
const CHECK_PATIENT_FOR_REGISTRATION = "Services/Authentication.svc/REST/CheckPatientForRegisteration";

const CHECK_USER_STATUS = "Services/NHIC.svc/REST/GetPatientInfo";
const REGISTER_USER = 'Services/Authentication.svc/REST/PatientRegistration';
const LOGGED_IN_USER_URL = 'Services/MobileNotifications.svc/REST/Insert_PatientMobileDeviceInfo';

const FORGOT_PATIENT_ID = 'Services/Authentication.svc/REST/SendPatientIDSMSByMobileNumber';
const DASHBOARD = 'Services/Patients.svc/REST/PatientDashboard';
const PROFILE_SETTING = 'Services/Patients.svc/REST/GetPateintInfoForUpdate';
const SAVE_SETTING = 'Services/Patients.svc/REST/UpdatePateintInfo';

class AuthProvider with ChangeNotifier {
  bool isLogin = false;
  bool isLoading = true;
  dynamic authenticatedUser;
  AuthenticatedUserObject authenticatedUserObject = locator<AuthenticatedUserObject>();

  AuthProvider() {
    getUserAuthentication();
  }

  void getUserAuthentication() async {
    Map profile = await sharedPref.getObject(USER_PROFILE);
    if (profile != null) {
      isLoading = false;
      isLogin = true;
    } else {
      isLoading = false;
      isLogin = false;
    }
    notifyListeners();
  }

  APP_STATUS get stutas {
    if (isLoading) {
      return APP_STATUS.LOADING;
    } else {
      if (this.isLogin) {
        return APP_STATUS.AUTHENTICATED;
      } else {
        return APP_STATUS.UNAUTHENTICATED;
      }
    }
  }

  // Future<dynamic> login(UserModel userInfo) async {
  //   try {
  //     dynamic localRes;

  //     await BaseAppClient.post(LOGIN_URL,
  //         onSuccess: (dynamic response, int statusCode) {
  //       localRes = response;
  //     }, onFailure: (String error, int statusCode) {
  //       throw error;
  //     }, body: userInfo.toJson());

  //     return Future.value(localRes);
  //   } catch (error) {
  //     print(error);
  //     throw error;
  //   }
  // }

  Future<dynamic> insertDeviceImei(lstLogin) async {
    try {
      dynamic localRes;
      var lastLogin = lstLogin; //await sharedPref.getInt(
      // LAST_LOGIN); //this.cs.sharedService.getStorage(AuthenticationService.LAST_LOGIN); //this.cs.sharedService.getSharedData(AuthenticationService.LAST_LOGIN, false);

      var request = AuthenticatedUser.fromJson(await sharedPref.getObject(USER_PROFILE));
      var newRequest = INSERTDeviceIMEIRequest();

      var imei = await sharedPref.getString(PUSH_TOKEN);
      // if (!request.) {
      newRequest.iMEI = imei; //imei!=null ? imei : '';
      newRequest.firstName = request.firstName ?? "" + " " + request.lastName ?? "";
      newRequest.firstNameN = request.firstNameN ?? "" + " " + request.lastNameN ?? "";
      newRequest.lastNameN = request.lastNameN ?? "";
      newRequest.outSA = request.outSA == 1 ? true : false;
      newRequest.biometricEnabled = false;
      newRequest.preferredLanguage = int.parse(request.preferredLanguage) ?? 1;
      newRequest.logInTypeID = lastLogin ?? 1;
      newRequest.patientID = request.patientID;
      newRequest.mobileNo = request.mobileNumber;
      newRequest.identificationNo = request.patientIdentificationNo;
      newRequest.patientIdentificationNo = request.patientIdentificationNo;
      newRequest.patientType = request.patientType;
      newRequest.setupID = request.setupID;
      newRequest.tokenID = await sharedPref.getString(TOKEN);
      // }

      await new BaseAppClient().post(INSERT_DEVICE_IMEI, onSuccess: (dynamic response, int statusCode) {
        localRes = response;
      }, onFailure: (String error, int statusCode) {
        throw error;
      }, body: newRequest.toJson());
      return Future.value(localRes);
    } catch (error) {
      print(error);
      throw error;
    }
  }

  Future<SelectDeviceIMEIRES> selectDeviceImei(imei) async {
    try {
      dynamic localRes;
      Map<String, dynamic> request = {};
      request['IMEI'] = imei;
      await new BaseAppClient().post(SELECT_DEVICE_IMEI, onSuccess: (dynamic response, int statusCode) {
        localRes = SelectDeviceIMEIRES.fromJson(response['Patient_SELECTDeviceIMEIbyIMEIList'][0]);
      }, onFailure: (String error, int statusCode) {
        throw error;
      }, body: request);
      return Future.value(localRes);
    } catch (error) {
      return Future.value(null);
    }
  }

  Future<dynamic> checkPatientAuthentication(CheckPatientAuthenticationReq request) async {
    request.versionID = VERSION_ID;
    request.channel = CHANNEL;
    request.iPAdress = IP_ADDRESS;
    request.generalid = GENERAL_ID;
    request.languageID = LANGUAGE_ID;
    request.patientOutSA = request.zipCode == '966' ? 0 : 1;
    try {
      dynamic localRes;
      await new BaseAppClient().post(CHECK_PATIENT_AUTH, onSuccess: (dynamic response, int statusCode) {
        localRes = response;
      }, onFailure: (String error, int statusCode) {
        throw error;
      }, body: request.toJson());
      return Future.value(localRes);
    } catch (error) {
      throw error;
      //throw error;
    }
  }

  Future<dynamic> getLoginInfo(request) async {
    request.versionID = VERSION_ID;
    request.channel = CHANNEL;
    request.iPAdress = IP_ADDRESS;
    request.generalid = GENERAL_ID;
    request.languageID = LANGUAGE_ID;
    request.deviceTypeID = DeviceTypeID;
    request.patientOutSA = request.zipCode == '966' ? 0 : 1;
    request.isDentalAllowedBackend = false;
    // request.patientTypeID = request.patientType;
    // request.patientType = request.patientType;
    dynamic localRes;
    await new BaseAppClient().post(GET_MOBILE_INFO, onSuccess: (dynamic response, int statusCode) {
      localRes = response;
    }, onFailure: (String error, int statusCode) {
      throw error;
    }, body: request.toJson());
    return Future.value(localRes);
  }

  Future<dynamic> sendActivationCode(request) async {
    request.versionID = VERSION_ID;
    request.channel = CHANNEL;
    request.iPAdress = IP_ADDRESS;
    request.generalid = GENERAL_ID;
    request.languageID = LANGUAGE_ID;
    request.deviceTypeID = DeviceTypeID;
    request.patientOutSA = request.zipCode == '966' ? 0 : 1;
    request.isDentalAllowedBackend = false;

    dynamic localRes;
    await new BaseAppClient().post(SEND_ACTIVATION_CODE, onSuccess: (dynamic response, int statusCode) {
      localRes = response;
      authenticatedUser = CheckActivationCode.fromJson(localRes);
    }, onFailure: (String error, int statusCode) {
      throw error;
    }, body: request.toJson());
    return Future.value(localRes);
  }

  Future<dynamic> sendActivationCodeRegister(request) async {
    request.versionID = VERSION_ID;
    request.channel = CHANNEL;
    request.iPAdress = IP_ADDRESS;
    request.generalid = GENERAL_ID;
    request.languageID = LANGUAGE_ID;
    request.deviceTypeID = DeviceTypeID;
    request.patientOutSA = request.zipCode == '966' ? 0 : 1;
    request.isDentalAllowedBackend = false;

    dynamic localRes;
    await new BaseAppClient().post(SEND_ACTIVATION_CODE_REGISTER, onSuccess: (dynamic response, int statusCode) {
      localRes = response;
      authenticatedUser = CheckActivationCode.fromJson(localRes);
    }, onFailure: (String error, int statusCode) {
      throw error;
    }, body: request.toJson());
    return Future.value(localRes);
  }

  Future<dynamic> checkActivationCode(request, [value]) async {
    var neRequest = CheckActivationCodeReq.fromJson(request);

    neRequest.activationCode = value ?? "0000";
    neRequest.isSilentLogin = value != null ? false : true;
    neRequest.versionID = VERSION_ID;
    neRequest.channel = CHANNEL;
    neRequest.iPAdress = IP_ADDRESS;
    neRequest.generalid = GENERAL_ID;
    // neRequest.languageID = LANGUAGE_ID;
    neRequest.deviceTypeID = DeviceTypeID;
    neRequest.patientOutSA = neRequest.zipCode == '966' ? 0 : 1;
    neRequest.projectOutSA = neRequest.zipCode == '966' ? false : true;
    neRequest.isDentalAllowedBackend = false;
    // neRequest.deviceToken =  null;
    neRequest.forRegisteration = neRequest.isRegister != null ? neRequest.isRegister : false;
    neRequest.isRegister = false;
    dynamic localRes;
    try {
      await new BaseAppClient().post(CHECK_ACTIVATION_CODE, onSuccess: (dynamic response, int statusCode) {
        localRes = response; //CheckActivationCode.fromJson();
      }, onFailure: (String error, int statusCode) {
        localRes = error;
        return Future.value(error);
        // throw error;
      }, body: neRequest.toJson());
      return Future.value(localRes);
    } catch (error) {
      throw localRes;
    }
  }

  Future<dynamic> checkActivationCodeRegister(request, [value]) async {
    var neRequest = CheckActivationCodeRegisterReq.fromJson(request);

    neRequest.activationCode = value ?? "0000";
    neRequest.isSilentLogin = value != null ? false : true;
    neRequest.versionID = VERSION_ID;
    neRequest.channel = CHANNEL;
    neRequest.iPAdress = IP_ADDRESS;
    neRequest.generalid = GENERAL_ID;
    // neRequest.languageID = LANGUAGE_ID;
    neRequest.deviceTypeID = DeviceTypeID;
    neRequest.patientOutSA = neRequest.zipCode == '966' ? 0 : 1;
    neRequest.projectOutSA = neRequest.zipCode == '966' ? false : true;
    neRequest.isDentalAllowedBackend = false;
    // neRequest.deviceToken =  null;
    neRequest.forRegisteration = neRequest.isRegister != null ? neRequest.isRegister : false;
    neRequest.isRegister = false;
    dynamic localRes;
    try {
      await new BaseAppClient().post(CHECK_ACTIVATION_CODE_REGISTER, onSuccess: (dynamic response, int statusCode) {
        localRes = response; //CheckActivationCode.fromJson();
      }, onFailure: (String error, int statusCode) {
        localRes = error;
        return Future.value(error);
        // throw error;
      }, body: neRequest.toJson());
      // sharedPref.setString(BLOOD_TYPE, localRes['PatientBloodType']);
      return Future.value(localRes);
    } catch (error) {
      throw localRes;
      //return Future.value(error);
    }
  }

  AuthenticatedUser getAuthenticatedUser() {
    this.isLogin = true;
    return authenticatedUser;
  }

  Future<dynamic> checkPatientForRegisteration(CheckPatientForRegistration request) async {
    request.versionID = VERSION_ID;
    request.channel = CHANNEL;
    request.iPAdress = IP_ADDRESS;
    request.generalid = GENERAL_ID;
    request.deviceTypeID = DeviceTypeID;
    request.languageID = LANGUAGE_ID;
    request.isRegister = false;
    // request.tokenID = '';
    dynamic localRes;
    try {
      await new BaseAppClient().post(CHECK_PATIENT_FOR_REGISTRATION, onSuccess: (dynamic response, int statusCode) {
        localRes = response;
      }, onFailure: (String error, int statusCode) {
        localRes = error;
        return Future.value(error);
      }, body: request.toJson());
      return Future.value(localRes);
    } catch (error) {
      throw error;
    }
  }

  Future<dynamic> checkUserStatus(CheckUserStatusRequest request) async {
    request.versionID = VERSION_ID;
    request.channel = CHANNEL;
    request.iPAdress = IP_ADDRESS;
    request.generalid = GENERAL_ID;
    request.deviceTypeID = DeviceTypeID;
    request.languageID = LANGUAGE_ID;

    // request.tokenID = '';
    dynamic localRes;
    try {
      await new BaseAppClient().post(CHECK_USER_STATUS, onSuccess: (dynamic response, int statusCode) {
        localRes = response;
      }, onFailure: (String error, int statusCode) {
        localRes = error;
        return Future.value(error);
      }, body: request.toJson());
      return Future.value(localRes);
    } catch (error) {
      throw error;
    }
  }

  Future<dynamic> registerUser(request) async {
    request['VersionID'] = VERSION_ID;
    request['Channel'] = CHANNEL;
    request['IPAdress'] = IP_ADDRESS;
    request['Generalid'] = GENERAL_ID;
    request['DeviceTypeID'] = DeviceTypeID;
    request['LanguageID'] = LANGUAGE_ID;
    request['LogInTokenID'] = await sharedPref.getString(LOGIN_TOKEN_ID);
    var nhic = await sharedPref.getObject(NHIC_DATA);
    var requestN = RegisterUserRequest.fromJson(request);
    requestN.patientOutSA = requestN.patientobject.patientOutSA;
    final DateFormat dateFormat = DateFormat('MM/dd/yyyy');
    final DateFormat dateFormat2 = DateFormat('dd/MM/yyyy');
    requestN.dob = nhic['IsHijri'] ? nhic['DateOfBirth'] : dateFormat2.format(dateFormat.parse(nhic['DateOfBirth']));
    requestN.zipCode = requestN.patientOutSA == 1 ? '971' : '966';
    requestN.healthId = requestN.patientobject.eHealthIDField;
    requestN.isHijri = nhic['IsHijri'] ? 1 : 0;
    await sharedPref.remove(USER_PROFILE);

    dynamic localRes;
    try {
      await new BaseAppClient().post(REGISTER_USER, onSuccess: (dynamic response, int statusCode) {
        localRes = response;
      }, onFailure: (String error, int statusCode) {
        localRes = error;
        return Future.value(error);
      }, body: requestN.toJson());
      return Future.value(localRes);
    } catch (error) {
      throw error;
    }
  }

  Future registeredAuthenticatedUser(AuthenticatedUser user, deviceToken, lat, long) async {
    var request = new RegisteredAuthenticatedUserRequest();
    request.deviceToken = deviceToken;
    request.voipToken = ""; //this.cs.sharedService.getSharedData(AuthenticationService.APNS_TOKEN, false);
    request.deviceType = DeviceTypeID.toString();
    request.patientMobileNumber = user.mobileNumber[0] == '0' ? user.mobileNumber : '0' + user.mobileNumber;
    request.nationalID = user.patientIdentificationNo;
    request.gender = user.gender;
    request.patientID = user.patientID;
    request.patientOutSA = user.outSA;
    request.loginType = await sharedPref.getInt(LAST_LOGIN) != null ? await sharedPref.getInt(LAST_LOGIN) : 1;
    request.mACAddress = '00:00:00:00:00:00';
    request.latitude = lat;
    request.longitude = long;
    request.languageID = int.parse(user.preferredLanguage);
    request.patientTypeID = user.patientType;
    request.patientType = user.patientType;
    dynamic localRes;
    try {
      await new BaseAppClient().post(LOGGED_IN_USER_URL, onSuccess: (dynamic response, int statusCode) {
        localRes = response;
      }, onFailure: (String error, int statusCode) {
        localRes = error;
        return Future.value(error);
      }, body: request.toJson());
      return Future.value(localRes);
    } catch (error) {
      throw error;
    }
  }

  Future<Map> sendPatientIDSMS(mobileNo, zipCode, context) async {
    Map<String, dynamic> request;

    Request req = appGlobal.getPublicRequest();
    request = {
      "PatientOutSA": zipCode == '+966' ? 0 : 1,
      "PatientMobileNumber": mobileNo,
      "SearchType": 2,
      "ZipCode": zipCode,
      "DeviceTypeID": req.DeviceTypeID,
    };

    dynamic localRes;

    await new BaseAppClient().post(FORGOT_PATIENT_ID, onSuccess: (response, statusCode) async {
      localRes = response;
    }, onFailure: (String error, int statusCode) {
      throw error;
    }, body: request);
    return Future.value(localRes);
  }

  Future<dynamic> forgotPasswordActivation(request, [value]) async {
    // var neRequest = CheckActivationCodeReq.fromJson(request);
    // neRequest.activationCode = value ?? "0000";
    // neRequest.isSilentLogin = value != null ? false : true;
    request['VersionID'] = VERSION_ID;
    request['Channel'] = CHANNEL;
    request['IPAdress'] = IP_ADDRESS;
    request['generalid'] = GENERAL_ID;
    request['LanguageID'] = LANGUAGE_ID;
    request['DeviceTypeID'] = DeviceTypeID;

    dynamic localRes;
    try {
      await new BaseAppClient().post(FORGOT_PASSWORD, onSuccess: (dynamic response, int statusCode) {
        localRes = response; //CheckActivationCode.fromJson();
      }, onFailure: (String error, int statusCode) {
        localRes = error;
        return Future.value(error);
        // throw error;
      }, body: request);
      return Future.value(localRes);
    } catch (error) {
      throw error;
      //return Future.value(error);
    }
  }

  Future<dynamic> getDashboard() async {
    Map<String, dynamic> request = {};
    // request['VersionID'] = VERSION_ID;
    // request['Channel'] = CHANNEL;
    // request['IPAdress'] = IP_ADDRESS;
    // request['generalid'] = GENERAL_ID;
    // request['LanguageID'] = LANGUAGE_ID;
    // request['DeviceTypeID'] = DeviceTypeID;

    dynamic localRes;
    try {
      await new BaseAppClient().post(DASHBOARD, onSuccess: (dynamic response, int statusCode) {
        localRes = response; //CheckActivationCode.fromJson();
      }, onFailure: (String error, int statusCode) {
        localRes = error;
        return Future.value(error);
        // throw error;
      }, body: request);
      return Future.value(localRes);
    } catch (error) {
      throw error;
      //return Future.value(error);
    }
  }

  getSettings() async {
    dynamic localRes;
    try {
      await new BaseAppClient().post(PROFILE_SETTING, onSuccess: (dynamic response, int statusCode) {
        localRes = response; //CheckActivationCode.fromJson();
      }, onFailure: (String error, int statusCode) {
        localRes = error;
        return Future.value(error);
        // throw error;
      }, body: {});
      return Future.value(localRes);
    } catch (error) {
      throw error;
      //return Future.value(error);
    }
  }

  Future saveSettings(request) async {
    dynamic localRes;
    try {
      await new BaseAppClient().post(SAVE_SETTING, onSuccess: (dynamic response, int statusCode) {
        localRes = response; //CheckActivationCode.fromJson();
      }, onFailure: (String error, int statusCode) {
        localRes = error;
        return Future.value(error);
        // throw error;
      }, body: request);
      return Future.value(localRes);
    } catch (error) {
      throw error;
      //return Future.value(error);
    }
  }
}
