import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:get/get.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:prosappco/src/authentication/exceptions/register_failed.dart';
import 'package:prosappco/src/models/event_model.dart';
import 'package:prosappco/src/screens/login.dart';
import 'package:prosappco/src/screens/service.dart';

class AuthenticationRepository extends GetxController {
  static AuthenticationRepository get instance => Get.find();

  //Variables
  final _auth = FirebaseAuth.instance;
  late final Rx<User?> firebaseUser;
  final firebase = FirebaseFirestore.instance;
  final GoogleSignIn googleSignIn = GoogleSignIn();
  // final _userRef = firebase
  var verificationId = ''.obs;

  @override
  void onReady() {
    // Future.delayed(const Duration(seconds: 6));
    firebaseUser = Rx<User?>(_auth.currentUser);
    firebaseUser.bindStream(_auth.userChanges());
    ever(firebaseUser, _setInitialScreen);
  }

  _setInitialScreen(User? user) {
    user == null
        ? Get.offAll(const LoginScreen())
        : Get.offAll(const ServiceScreen());
  }

  Future<void> phoneAuthentication(String phoneNo) async {
    await _auth.verifyPhoneNumber(
      phoneNumber: phoneNo,
      verificationCompleted: (credential) async {
        await _auth.signInWithCredential(credential);
      },
      codeSent: (verificationId, resendToken) {
        this.verificationId.value = verificationId;
      },
      codeAutoRetrievalTimeout: (verificationId) {
        this.verificationId.value = verificationId;
      },
      verificationFailed: (e) {
        if (e.code == 'invalid-phone-number') {
          Get.snackbar('Error', 'El numero no es valido.');
        } else {
          Get.snackbar('Error', 'Algo ha ido mal. Inténtalo de nuevo. $e');
        }
      },
    );
  }

  Future<void> updatePhoneNumber(String verificationId, String smsCode) async {
    try {
      PhoneAuthCredential credential = PhoneAuthProvider.credential(
          verificationId: verificationId, smsCode: smsCode);
      await FirebaseAuth.instance.currentUser!.updatePhoneNumber(credential);
      print("Phone number updated successfully");
    } catch (e) {
      print("Error updating phone number: $e");
    }
  }

  Future<bool> verifyOTP(String otp) async {
    var credentials = await _auth.signInWithCredential(
        PhoneAuthProvider.credential(
            verificationId: verificationId.value, smsCode: otp));
    return credentials.user != null ? true : false;
  }

  Future<void> createUserWithEmailAndPassword(
      String email, String password) async {
    try {
      await _auth.createUserWithEmailAndPassword(
          email: email, password: password);

      firebaseUser.value != null
          ? Get.offAll(const ServiceScreen())
          : Get.to(const LoginScreen());
    } on FirebaseAuthException catch (e) {
      final ex = SignUpWithEmailAndPasswordFailure.code(e.code);
      Get.snackbar(
        'Correo ya registrado',
        'Por favor pruebe con otro.',
        snackPosition: SnackPosition.BOTTOM,
      );
    } catch (_) {
      const ex = SignUpWithEmailAndPasswordFailure();
      print('EXCEPTION - ${ex.message}');
      throw ex;
    }
  }

  Future<void> loginWithEmailAndPassword(String email, String password) async {
    try {
      await _auth.signInWithEmailAndPassword(email: email, password: password);
    } on FirebaseAuthException catch (e) {
      if (e.code == 'wrong-password') {
        Get.snackbar(
          'Contraseña incorrecta',
          'Por favor intentelo de nuevo.',
          snackPosition: SnackPosition.BOTTOM,
        );
      }
      if (e.code == 'invalid-email') {
        Get.snackbar(
          'Ingrese un email valido',
          'Por favor pruebe con otro.',
          snackPosition: SnackPosition.BOTTOM,
        );
      }
      if (e.code == 'user-not-found') {
        Get.snackbar(
          'Email no encontrado',
          'Este correo no se encuentra registrado.',
          snackPosition: SnackPosition.BOTTOM,
        );
      }
    } catch (_) {}
  }

  Future<void> signInWithGoogle() async {
    try {
      final GoogleSignInAccount? googleUser = await GoogleSignIn().signIn();

      if (googleUser != null) {
        final GoogleSignInAuthentication googleAuth =
            await googleUser.authentication;
        final OAuthCredential credential = GoogleAuthProvider.credential(
          accessToken: googleAuth.accessToken,
          idToken: googleAuth.idToken,
        );

        await FirebaseAuth.instance.signInWithCredential(credential);

        // Continúa con el flujo de la aplicación después del inicio de sesión exitoso
        // Por ejemplo, redirecciona a la siguiente pantalla
        firebaseUser.value != null
            ? Get.offAll(const ServiceScreen())
            : Get.to(const LoginScreen());
      } else {
        // El usuario canceló el inicio de sesión con Google
        // Puedes manejarlo según tus necesidades
        print('Error');
      }
    } catch (e) {
      print('Error - $e');
    }
  }

  Future<void> logout(String uid) async {
    try {
      await FirebaseFirestore.instance
          .collection('users')
          .doc(uid)
          .update({'token': FieldValue.delete()});
    } catch (e) {
      print(e);
    }

    _auth.signOut();
  }

  String? getCurrentUserPhone() {
    final User? user = _auth.currentUser;
    return user?.phoneNumber;
  }

  String? getCurrentUserUid() {
    final User? user = _auth.currentUser;
    return user?.uid;
  }

  Future<String> getCity(String uid) async {
    String city = '';
    try {
      final snapshot =
          await FirebaseFirestore.instance.collection('users').doc(uid).get();
      final Map<String, dynamic>? data = snapshot.data();
      city = data?['city'] ?? '';
    } catch (e) {
      print('Error getting city: $e');
    }
    return city;
  }

  Future<String> getCoordsOfCity(String uid) async {
    String coords = '';
    try {
      final snapshot =
          await FirebaseFirestore.instance.collection('users').doc(uid).get();
      final Map<String, dynamic>? data = snapshot.data();
      coords = data?['coordsOfCity'] ?? '';
    } catch (e) {
      print('Error getting coords of city: $e');
    }
    print('Error getting coords of city: $coords');
    return coords;
  }

  Future<String> getAddress(String uid) async {
    String address = '';
    try {
      final snapshot =
          await FirebaseFirestore.instance.collection('users').doc(uid).get();
      final Map<String, dynamic>? data = snapshot.data();
      address = data?['address'] ?? '';
    } catch (e) {
      print('Error getting address: $e');
    }
    return address;
  }

  Future<String> getUbicacion(String uid) async {
    String location = '';
    try {
      final snapshot =
          await FirebaseFirestore.instance.collection('users').doc(uid).get();
      final Map<String, dynamic>? data = snapshot.data();
      location = data?['ubicacion'] ?? '';
    } catch (e) {
      print('Error getting address: $e');
    }
    return location;
  }

  Future<String> getOpcionalAddress(String uid) async {
    String opcional_location = '';
    try {
      final snapshot =
          await FirebaseFirestore.instance.collection('users').doc(uid).get();
      final Map<String, dynamic>? data = snapshot.data();
      opcional_location = data?['opcional_address'] ?? '';
    } catch (e) {
      print('Error getting address: $e');
    }
    return opcional_location;
  }

  Future<int> getTarifa(String uid) async {
    int tarifa = 0;
    try {
      final snapshot =
          await FirebaseFirestore.instance.collection('users').doc(uid).get();
      final Map<String, dynamic>? data = snapshot.data();
      tarifa = data?['tarifa'] ?? 0;
    } catch (e) {
      print('Error getting tarifa: $e');
    }
    return tarifa;
  }

  Future<String> getPhoto(String uid) async {
    String photo = '';
    try {
      final snapshot =
          await FirebaseFirestore.instance.collection('users').doc(uid).get();
      final Map<String, dynamic>? data = snapshot.data();
      photo = data?['photo'] ?? '';
    } catch (e) {
      print('Error getting photo: $e');
    }
    return photo;
  }

  Future<String> getBanner(String uid) async {
    String photo = '';
    try {
      final snapshot =
          await FirebaseFirestore.instance.collection('users').doc(uid).get();
      final Map<String, dynamic>? data = snapshot.data();
      photo = data?['banner'] ?? '';
    } catch (e) {
      print('Error getting banner: $e');
    }
    return photo;
  }

  Future<String> getProfession(String uid) async {
    String profession = '';
    try {
      final snapshot =
          await FirebaseFirestore.instance.collection('users').doc(uid).get();
      final Map<String, dynamic>? data = snapshot.data();
      profession = data?['profesion'] ?? '';
    } catch (e) {
      print('Error getting profesion: $e');
    }
    return profession;
  }

  Future<String> getState(String uid) async {
    String state = '';
    try {
      final snapshot =
          await FirebaseFirestore.instance.collection('users').doc(uid).get();
      final Map<String, dynamic>? data = snapshot.data();
      state = data?['estado'] ?? '';
    } catch (e) {
      print('Error getting estado: $e');
    }
    return state;
  }
}
