/* eslint-disable react/display-name */
import { useDataFromRef } from "react-native-minuit/src/hooks";
import useMinuit from "react-native-minuit/src/hooks/useMinuit";
import { createContext, useContext, useGlobal } from "reactn";

import { useState } from "react";
import { checkIfEmailIsValid } from "../actions/signupActions";
import firebase, {
  arrayRemove,
  arrayUnion,
  playlistsRef,
  projectsRef,
  usersRef,
} from "../config/firebase";

export const UserDataContext = createContext();

export default ({ children }) => {
  const { setIsLoading, setTooltip } = useMinuit();

  const [pendingUserData, setPendingUserData] = useState({
    creationTimestamp: new Date(),
  });

  const [currentUID] = useGlobal("currentUID");
  const [currentUserData, setCurrentUserData] = useGlobal("currentUserData");
  const [currentUserRoles] = useGlobal("currentUserRoles");
  // Current user document (live)
  const { data: currentUserDoc = null } = useDataFromRef({
    ref: currentUID ? usersRef.doc(currentUID) : null,
    updateGlobalState: "currentUserData",
    simpleRef: true,
    listener: true,
    condition: !!currentUID,
    refreshArray: [currentUID],
  });

  // Subscribe to user's projects (musics)
  const { data: userProjects = [] } = useDataFromRef({
    ref: currentUID
      ? projectsRef
          .where("userId", "==", currentUID)
          .orderBy("updatedAt", "desc")
      : null,
    simpleRef: false,
    listener: true,
    condition: !!currentUID,
    refreshArray: [currentUID],
  });

  const userPlaybacks = Array.isArray(userProjects)
    ? userProjects.filter((project) => project.playbackUrl)
    : [];
  // Subscribe to user's liked projects
  const { data: userLikedProjects = [] } = useDataFromRef({
    ref: currentUID
      ? projectsRef
          .where("likedBy", "array-contains", currentUID)
          .orderBy("updatedAt", "desc")
      : null,
    simpleRef: false,
    listener: true,
    condition: !!currentUID,
    refreshArray: [currentUID],
  });

  // Subscribe to user's playlists
  const { data: userPlaylists = [] } = useDataFromRef({
    ref: currentUID ? playlistsRef.where("createdBy", "==", currentUID) : null,
    simpleRef: false,
    listener: true,
    condition: !!currentUID,
    refreshArray: [currentUID],
  });

  // Live list of users that the current user is following ("abonnements")
  const { data: userFollowing = [] } = useDataFromRef({
    ref: currentUID
      ? usersRef.where("followedBy", "array-contains", currentUID)
      : null,
    simpleRef: false,
    listener: true,
    condition: !!currentUID,
    refreshArray: [currentUID],
  });

  const updatePendingUserData = (newData) => {
    setPendingUserData((prevData) => ({
      ...prevData,
      ...newData,
    }));
  };
  const followUser = async (userId) => {
    try {
      if (currentUID && userId) {
        await usersRef.doc(userId).set(
          {
            followedBy: arrayUnion(currentUID),
            lastFollowersUpdateAt: new Date(),
          },
          { merge: true }
        );
        setTooltip({ type: "success", text: "Abonnement mis à jour" });
      }
    } catch (e) {
      console.log(e);
      setTooltip({ type: "error", text: e?.message || "Action impossible" });
    }
  };

  const unfollowUser = async (userId) => {
    try {
      if (currentUID && userId) {
        await usersRef.doc(userId).set(
          {
            followedBy: arrayRemove(currentUID),
            lastFollowersUpdateAt: new Date(),
          },
          { merge: true }
        );
        setTooltip({
          type: "success",
          text: "Vous ne suivez plus cet utilisateur",
        });
      }
    } catch (e) {
      console.log(e);
      setTooltip({ type: "error", text: e?.message || "Action impossible" });
    }
  };
  const getUserByUid = async (uid) => {
    try {
      const userDoc = await usersRef.doc(uid).get();
      return userDoc.exists
        ? {
            id: userDoc.id,
            ...userDoc.data(),
          }
        : null;
    } catch (e) {
      console.log(e);
      return null;
    }
  };

  const updateUserData = async ({ data, shouldSetTooltip = true }) => {
    try {
      await setIsLoading(true);

      let dynamicUID = currentUID || null;

      let cleanData = {
        ...currentUserData,
        ...data,
        lastUpdateTimestamp: new Date(),
      };

      // if (cleanData?.firstName?.length > 2 && cleanData?.lastName?.length > 2) {
      //   cleanData = {
      //     ...cleanData,
      //     firstName: capitalize(cleanData?.firstName?.toLowerCase()),
      //     lastName: capitalize(cleanData?.lastName?.toLowerCase()),
      //   };
      // } else {
      //   throw new Error("Veuillez renseigner un prénom et un nom");
      // }

      if (!checkIfEmailIsValid({ email: cleanData?.email })) {
        throw new Error("Veuillez renseigner un email valide");
      }

      // let cleanPhoneNumber = formatPhoneNumber({
      //   phoneNumber: cleanData.phoneNumber,
      // });

      // if (cleanPhoneNumber) {
      //   cleanData.phoneNumber = cleanPhoneNumber;
      // } else {
      //   throw new Error("Veuillez renseigner un numéro de téléphone valide");
      // }

      if (!dynamicUID) {
        const { email, password } = cleanData;

        const { user = null } = await firebase
          .auth()
          .createUserWithEmailAndPassword(email, password);

        dynamicUID = user.uid;
      }

      delete cleanData.password;

      cleanData = {
        ...cleanData,
        userID: dynamicUID,
      };

      if (!cleanData?.creationTimestamp) {
        cleanData.creationTimestamp = new Date();
      }

      await usersRef.doc(dynamicUID).set(cleanData, { merge: true });

      if (shouldSetTooltip) {
        setTooltip({
          type: "success",
          text: "Données enregistrées avec succès",
        });
      }
    } catch (e) {
      console.log(e);

      setTooltip({
        type: "error",
        text: "Erreur lors de la mise à jour des données utilisateur",
      });

      throw e;
    } finally {
      await setIsLoading(false);
    }
  };

  const onSignOut = async () => {
    try {
      setIsLoading(true);

      await firebase.auth().signOut();
    } catch (e) {
      console.log(e);
    } finally {
      setIsLoading(false);
    }
  };

  const isSuperAdmin = currentUserRoles.some((role) => role === "SUPERADMIN");

  return (
    <UserDataContext.Provider
      value={{
        isSuperAdmin,

        currentUserRoles,
        currentUID,
        currentUserData: currentUserDoc,
        userProjects,
        userPlaybacks,
        userLikedProjects,
        userPlaylists,
        followingCount: userFollowing?.length || 0,

        setCurrentUserData,
        getUserByUid,
        onSignOut,

        pendingUserData,
        updatePendingUserData,

        updateUserData,
        followUser,
        unfollowUser,
      }}
    >
      {children}
    </UserDataContext.Provider>
  );
};

export const useUserData = () => {
  return useContext(UserDataContext);
};

// Convenience alias returning the same context, as requested
export const useUser = () => {
  return useContext(UserDataContext);
};
