/* eslint-disable */
import { Provider } from 'function-tree';
import firebaseAdmin from 'firebase-admin';
import createTask from './createTask';
import username from 'username';

function noReturnValue() {}

const task = createTask({ specPrefix: username.sync() });

function firebaseAdminProvider(providerOptions = {}, customFirebaseInstance) {
  const firebase = customFirebaseInstance || firebaseAdmin;

  if (!customFirebaseInstance) {
    if (!providerOptions.serviceAccount || !providerOptions.databaseURL) {
      throw new Error(
        'FIREBASE: You are not passing correct providerOptions to provider'
      );
    }

    firebase.initializeApp({
      credential: firebase.credential.cert(providerOptions.serviceAccount),
      databaseURL: providerOptions.databaseURL,
    });
  }

  return new Provider({
    verifyIdToken(token) {
      return firebase.auth().verifyIdToken(token || '');
    },
    createKey(path) {
      return firebase
        .database()
        .ref(path)
        .push().key;
    },
    getAllUsers() {
      return new Promise((resolve, reject) => {
        let allUsers = [];

        function listAllUsers(nextPageToken) {
          // Get batch of users, 1000 at a time. 1000 is max.
          firebase
            .auth()
            .listUsers(1000, nextPageToken)
            .then(listUsersResult => {
              allUsers = allUsers.concat(listUsersResult.users);
              if (listUsersResult.pageToken) {
                // List next batch of users.
                listAllUsers(listUsersResult.pageToken);
              } else {
                resolve({ value: allUsers });
              }
            })
            .catch(error => {
              reject(error);
            });
        }
        listAllUsers();
      });
    },
    deleteUser(uid) {
      return firebase.auth().deleteUser(uid);
    },
    remove(path) {
      const ref = firebase.database().ref(path);

      return ref.remove().then(noReturnValue);
    },
    getUserByEmail(email) {
      return firebase.auth().getUserByEmail(email);
    },
    push(path, value) {
      const ref = firebase
        .database()
        .ref(path)
        .push();

      return ref.set(value).then(() => ({ key: ref.key }));
    },
    set(path, value) {
      return firebase
        .database()
        .ref(path)
        .set(value)
        .then(noReturnValue);
    },
    sendMessage(message) {
      return firebase.messaging().send(message);
    },
    update(path, value) {
      if (path && value) {
        return firebase
          .database()
          .ref(path)
          .update(value)
          .then(noReturnValue);
      }

      return firebase
        .database()
        .update(path)
        .then(noReturnValue);
    },
    value(path, options = {}) {
      return new Promise((resolve, reject) => {
        Object.keys(options)
          .reduce(
            (currentRef, optionKey) =>
              currentRef[optionKey](options[optionKey]),
            firebase.database().ref(path)
          )
          .once(
            'value',
            snapshot => {
              resolve({
                key: path.split('/').pop(),
                value: snapshot.val(),
              });
            },
            reject
          );
      });
    },
    transaction(path, cb) {
      return firebase
        .database()
        .ref(path)
        .transaction(cb)
        .then(noReturnValue);
    },
    task(name, payload) {
      task(name, payload);
    },
    getFile(url) {
      return firebase.storage().bucket().file(url).download();
    }
  });
}

export default firebaseAdminProvider;
