import 'package:get/get.dart';
import 'package:taafee_mobile/core/local_storage/local_storage.dart';
import 'package:taafee_mobile/core/routing/routing_manager.dart';
import 'package:taafee_mobile/features/auth/data_layer/model/forgot_password.dart';
import 'package:taafee_mobile/features/auth/data_layer/model/login.dart';
import 'package:taafee_mobile/features/auth/data_layer/model/login_response.dart';
import 'package:taafee_mobile/features/auth/data_layer/model/register.dart';
import 'package:taafee_mobile/features/auth/data_layer/model/reset_token.dart';
import 'package:taafee_mobile/features/auth/data_layer/model/user.dart';
import 'package:taafee_mobile/features/auth/data_layer/model/verification_code.dart';
import 'package:taafee_mobile/features/auth/data_layer/source/auth_service.dart';
import 'package:rx_future/rx_future.dart';

class AuthController extends GetxController {
//------------Data source
  AuthService authService = AuthService();
  LocalStorage storage = LocalStorage();

  //------------register-----------//
  RegisterModel registerModel = RegisterModel.zero();

  RxFuture<void> registerModelState = RxFuture(null);

  Future<void> register(
      {void Function(void)? onSuccess, void Function(Object)? onError}) async {
    await registerModelState.observe((p0) async {
      await authService.register(registerModel);
    }, onSuccess: (value) {
      verificationCodeModel.email = registerModel.email;
      onSuccess?.call(value);
    }, onError: onError);
  }

  //--------------verification code------------------//
  RxFuture<void> verifyState = RxFuture(null);
  VerificationCodeModel verificationCodeModel = VerificationCodeModel.zero();

  Future<void> verify(
      {void Function(void)? onSuccess, void Function(Object)? onError}) async {
    await verifyState.observe(
      (p0) async {
        await authService.verify(verificationCodeModel);
      },
      onSuccess: (value) async {
        if (loginModel.email == '' || loginModel.password == '') {
          loginModel.email = registerModel.email;
          loginModel.password = registerModel.password;
        }

        await login(
          onSuccess: (p0) {
            storage.saveIsGuest(false);
            storage.saveUser(p0.user);
            storage.saveToken(p0.token);
            onSuccess?.call(value);
          },
        );
      },
      onError: (error) {
        onError?.call(error);
      },
    );
  }

  //-----------------login---------------------//

  RxFuture<LoginResponseModel> loginState = RxFuture(LoginResponseModel.zero());

  LoginModel loginModel = LoginModel.zero();

  Future<void> login(
      {void Function(LoginResponseModel)? onSuccess,
      void Function(Object)? onError}) async {
    await loginState.observe(
      (p0) async {
        return await authService.login(loginModel);
      },
      onSuccess: (value) async {
        onSuccess?.call(value);
        await storage.saveUser(value.user);
        storage.saveToken(value.token);
        storage.saveChatToken(value.chatToken);
        storage.saveChatUserId(value.chatUserId);
        isGuest = false.obs;
        storage.saveIsGuest(false);
      },
      onError: (error) {
        if (error.toString() == "User is not verified") {
          verificationCodeModel.email = loginModel.email;
        }
        onError?.call(error);
      },
    );
  }

  ///---------logout--------///
  RxFuture<void> logoutState = RxFuture(null);

  Future<void> logout({void Function(void)? onSuccess}) async {
    loginModel = LoginModel.zero();
    await logoutState.observe(
      (p0) async {
        await authService.logout();
      },
      onSuccess: (value) async {
        isGuest = false.obs;
        storage.saveIsGuest(false);
        String? languangeCode = storage.getLanguage();
        await storage.clearCache();
        if (languangeCode != null) {
          storage.saveLanguage(languangeCode);
        }
        onSuccess?.call(value);
      },
    );
  }

  ///---------resend code----------------//
  RxFuture<void> resendCodeState = RxFuture(null);
  Future<void> resendCode(String email) async {
    await resendCodeState.observe((p0) async {
      await authService.resendCode(email);
    });
  }

  ///----------forgot password---------//
  ForgotPasswordModel forgotPasswordModel = ForgotPasswordModel.zero();

  RxFuture<void> forgotPasswordState = RxFuture(null);
  Future<void> forgotPassword(
      {void Function(void)? onSuccess, void Function(Object)? onError}) async {
    await forgotPasswordState.observe(
      (p0) async {
        await authService.forgotPassword(forgotPasswordModel.email);
      },
      onSuccess: (value) {
        onSuccess?.call(value);
      },
      onError: (error) {
        onError?.call(error);
      },
    );
  }

  ///------------verify forgot password-----------///
  RxFuture<ResetToken> verifyForgotPasswordState = RxFuture(ResetToken.zero());

  Future<void> verifyForgotPassword(
      {void Function(ResetToken)? onSuccess,
      void Function(Object)? onError}) async {
    await verifyForgotPasswordState.observe(
      (p0) async {
        return await authService.verifyForgotPassword(
            forgotPasswordModel.email, forgotPasswordModel.code);
      },
      onSuccess: (value) {
        onSuccess?.call(value);
      },
      onError: (error) {
        onError?.call(error);
      },
    );
  }

  ///------------change password----------///
  RxFuture<void> changePasswordState = RxFuture(null);

  Future<void> changePassword(
      {void Function(void)? onSuccess, void Function(Object)? onError}) async {
    await changePasswordState.observe(
      (p0) async {
        await authService.changePassword(
          verifyForgotPasswordState.result.resetToken,
          forgotPasswordModel.password,
        );
      },
      onSuccess: (p0) async {
        loginModel.email = forgotPasswordModel.email;
        loginModel.password = forgotPasswordModel.password;
        await login(
          onSuccess: (value) {
            isGuest = false.obs;
            storage.saveUser(value.user);
            storage.saveToken(value.token);
            onSuccess?.call(p0);
          },
        );
      },
      onError: (error) {
        onError?.call(error);
      },
    );
  }

  ///--------delete account-----///
  RxFuture<void> deleteAccountState = RxFuture(null);
  String password = '';
  Future<void> deleteAccount(
      {void Function(void)? onSuccess, void Function(Object)? onError}) async {
    await deleteAccountState.observe(
      (p0) async {
        await authService.deleteAccount(password);
      },
      onSuccess: (value) {
        isGuest = true.obs;
        onSuccess?.call(value);
        String? languangeCode = storage.getLanguage();
        storage.clearCache();
        if (languangeCode != null) {
          storage.saveLanguage(languangeCode);
        }
      },
      onError: (error) {
        onError?.call(error);
      },
    );
  }

  /// ------------- terminate other sessions ---------///
  RxFuture<void> terminateOtherSessionsState = RxFuture(null);
  Future<void> terminateOtherSessions(
      {void Function(void)? onSuccess, void Function(Object)? onError}) async {
    terminateOtherSessionsState.observe((value) async {
      return await authService.terminateOtherSessions();
    }, onSuccess: (value) {
      onSuccess?.call(value);
    }, onError: (err) {
      onError?.call(err);
    });
  }

  ///----------- obsecure password -------///

  //register screen
  RxBool registerPassowrdVisible = false.obs;
  void toggleRegisterPassowrdVisibilty() {
    registerPassowrdVisible.value = !registerPassowrdVisible.value;
    registerPassowrdVisible.refresh();
  }

  RxBool registerConfirmPassowrdVisible = false.obs;
  void toggleRegisterConfirmPassowrdVisibilty() {
    registerConfirmPassowrdVisible.value =
        !registerConfirmPassowrdVisible.value;
    registerConfirmPassowrdVisible.refresh();
  }

  RxBool loginPasswordVisible = false.obs;
  RxBool changePasswordNewPasswordVisible = false.obs;
  RxBool changePasswordConfirmPasswordVisible = false.obs;
  RxBool changePasswordOldPasswordVisible = false.obs;
  RxBool resetPasswordNewPasswordVisible = false.obs;
  RxBool resetPasswordConfirmPasswordVisible = false.obs;
  void toggleLoginPasswordVisibility() {
    loginPasswordVisible.value = !loginPasswordVisible.value;
    loginPasswordVisible.refresh();
  }

  void toggleChangePasswordNewPasswordVisibility() {
    changePasswordNewPasswordVisible.value =
        !changePasswordNewPasswordVisible.value;
    changePasswordNewPasswordVisible.refresh();
  }

  void toggleChangePasswordConfirmPasswordVisibility() {
    changePasswordConfirmPasswordVisible.value =
        !changePasswordConfirmPasswordVisible.value;
    changePasswordConfirmPasswordVisible.refresh();
  }

  void toggleChangePasswordOldPasswordVisibility() {
    changePasswordOldPasswordVisible.value =
        !changePasswordOldPasswordVisible.value;
    changePasswordOldPasswordVisible.refresh();
  }

  void toggleResetPasswordNewPasswordVisibility() {
    resetPasswordNewPasswordVisible.value =
        !resetPasswordNewPasswordVisible.value;
    resetPasswordNewPasswordVisible.refresh();
  }

  void toggleResetPasswordConfirmPasswordVisibility() {
    resetPasswordConfirmPasswordVisible.value =
        !resetPasswordConfirmPasswordVisible.value;
    resetPasswordConfirmPasswordVisible.refresh();
  }

  /// -------------guest--------------///
  RxBool isGuest = false.obs;
  RxFuture<String> guestState = RxFuture('');
  void guestSignIn({void Function(Object)? onError}) {
    guestState.observe((p0) async {
      return await authService.guest();
    }, onSuccess: (token) {
      isGuest = true.obs;
      storage.saveToken(token);
      storage.saveIsGuest(true);
      storage.saveUser(User(
          id: 0,
          firstName: 'guest',
          lastName: '',
          email: '',
          chatUserId: 0,
          avatarImage: null));
      RoutingManager.off(RouteName.superHome);
    }, onError: onError);
  }
}
