import FuseUtils from '@fuse/utils/FuseUtils';
import _ from '@lodash';
import * as firebaseAuth from 'firebase/auth';
import * as firebaseDb from 'firebase/database';

export default class AuthService extends FuseUtils.EventEmitter {
  #auth;

  #db;

  init(authInstance, dbInstance) {
    this.#auth = authInstance;
    this.#db = dbInstance;
  }

  createUser = ({ displayName, email, password }) => {
    return new Promise((resolve, reject) => {
      firebaseAuth
        .createUserWithEmailAndPassword(this.#auth, email, password)
        .then((userCredential) => firebaseAuth.updateProfile(userCredential.user, { displayName }))
        .then(() => {
          const userRef = firebaseDb.ref(this.#db, `users/${this.#auth.currentUser.uid}`);
          const value = { role: 'user', data: { displayName, email }, favorites: [] };

          return firebaseDb.set(userRef, value);
        })
        .then(() => {
          resolve();
        })
        .catch((error) => {
          reject(error);
        });
    });
  };

  signInWithEmailAndPassword = ({ email, password, remember }) => {
    const persistence = remember
      ? firebaseAuth.browserLocalPersistence
      : firebaseAuth.browserSessionPersistence;

    return new Promise((resolve, reject) => {
      firebaseAuth
        .setPersistence(this.#auth, persistence)
        .then(() => firebaseAuth.signInWithEmailAndPassword(this.#auth, email, password))
        .then((userCredential) => {
          resolve(userCredential.user);
          const { user } = userCredential;
          this.emit('onLogin', {
            role: 'user',
            data: { displayName: user.displayName, photoURL: user.photoURL, email: user.email },
          });
        })
        .catch((error) => {
          reject(error);
        });
    });
  };

  updateUserData = (user) => {
    return new Promise((resolve, reject) => {
      if (_.isEmpty(user)) {
        reject(Error('User data is empty'));
      }

      const userRef = firebaseDb.ref(this.#db, `users/${this.#auth.currentUser.uid}`);

      firebaseDb
        .set(userRef, user)
        .then(() => {
          if (user.data.email !== this.#auth.currentUser.email) {
            return firebaseAuth.updateEmail(this.#auth, user.data.email);
          }

          return null;
        })
        .then(() => {
          resolve();
        })
        .catch((error) => {
          reject(error);
        });
    });
  };

  logout = () => {
    this.#auth
      .signOut()
      .then(() => {
        this.emit('onLogout', 'Logged out');
      })
      .catch((error) => {
        console.warn('Logout error: ', error);
      });
  };

  getUserData = (userId) => {
    return new Promise((resolve, reject) => {
      const userRef = firebaseDb.ref(this.#db, `users/${userId}`);
      firebaseDb.onValue(
        userRef,
        (snapshot) => {
          const user = snapshot.val();
          resolve(user);
        },
        (error) => {
          reject(error);
        }
      );
    });
  };

  sendPasswordResetEmail = (email) => {
    return new Promise((resolve, reject) => {
      if (!email) {
        reject(Error('Email is empty'));
      }

      firebaseAuth
        .sendPasswordResetEmail(this.#auth, email)
        .then(() => {
          resolve();
        })
        .catch((error) => {
          reject(error);
        });
    });
  };

  onAuthStateChanged = (callback) => {
    if (!this.#auth) {
      return;
    }

    this.#auth.onAuthStateChanged(callback);
  };
}
