import { defineStore } from 'pinia';
import type { getAuth, User } from 'firebase/auth';
import {
  serverTimestamp,
  doc,
  getDoc,
  setDoc,
  onSnapshot,
} from 'firebase/firestore';
import { createSession, logoutSession } from '@/utils/api/authFromFunction';
import {
  createUserWithEmailAndPassword,
  updateProfile,
  signInWithEmailAndPassword,
  signOut as firebaseSignOut,
} from 'firebase/auth';

let auth: ReturnType<typeof getAuth> | null = null;
let usersCollection: any = null;
let firebaseBase: string = '';

type UnsubscribeFn = (() => void) | null;

interface State {
  userLoggedIn: boolean;
  email: string;
  userRole: number;
  docId: string;
  isActive: boolean;
  name: string;
  profile_img: string;
  unsubscribe: UnsubscribeFn;
}

interface RegisterValues {
  email: string;
  password: string;
  name: string;
  membership: string;
  isActive: boolean;
  profile_img: string;
  created: any;
  uid: string;
  phone: number;
}

interface AuthenticateValues {
  email: string;
  password: string;
}

//delaying
function sleep(ms: number) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

export const useUserStore = defineStore('user', {
  state: (): State => ({
    userLoggedIn: false,
    email: '',
    docId: '',
    userRole: 0,
    isActive: false,
    profile_img: '',
    name: '',
    unsubscribe: null,
  }),
  actions: {
    init() {
      const { $firebase } = useNuxtApp();
      const auth = $firebase.auth;
      let everLoggedIn = false;
      auth.onIdTokenChanged(async (user: User | null) => {
        if (user) {
          everLoggedIn = true;
          const idToken = await user.getIdToken();
          await createSession(idToken);
          this.userLoggedIn = true;
          this.initializeListener();
        } else if (everLoggedIn) {
          // only really sign out if we *were* logged in
          await logoutSession();
          this._resetStore();
        }
      });
    },
    _resetStore() {
      this.userLoggedIn = false;
      this.email = '';
      this.docId = '';
      this.userRole = 0;
      this.isActive = false;
      this.name = '';
      this.profile_img = '';

      if (this.unsubscribe) {
        this.unsubscribe();
        this.unsubscribe = null;
      }
    },

    initializeListener() {
      const { $firebase } = useNuxtApp();
      auth = $firebase.auth;
      usersCollection = $firebase.usersCollection;

      if (!auth || !usersCollection) {
        throw new Error('Firebase not initialized');
      }

      const user = auth.currentUser;
      if (this.unsubscribe) {
        this.unsubscribe();
      }
      if (user) {
        const userDocRef = doc(usersCollection, user.uid);
        this.unsubscribe = onSnapshot(userDocRef, (docSnapshot) => {
          const userData = docSnapshot.data();
          if (userData) {
            this.$patch({
              userRole: userData.role,
              isActive: userData.isActive,
              name: userData.name,
              profile_img: userData.thumbnail_url,
              docId: userData.docId,
              email: userData.email,
            });
          }
        });
      }
    },
    async fetchUserInfo() {
      if (!auth || !usersCollection)
        throw new Error('Firebase not initialized');

      const currentUser = auth.currentUser;
      if (!currentUser) return null;

      const userDocRef = doc(usersCollection, currentUser.uid);
      const userSnap = await getDoc(userDocRef);

      if (userSnap.exists()) {
        this.docId = userSnap.id;
        return this.docId;
      }

      return null;
    },
    async register(values: RegisterValues) {
      if (!auth || !usersCollection)
        throw new Error('Firebase not initialized');

      const userCred = await createUserWithEmailAndPassword(
        auth,
        values.email,
        values.password
      );

      if (!userCred.user) {
        throw new Error('User creation failed.');
      }

      const userId = userCred.user.uid;

      // Use setDoc + doc() with serverTimestamp
      await setDoc(doc(usersCollection, userId), {
        docId: userId,
        name: values.name,
        email: values.email,
        membership: values.membership,
        role: 1,
        isActive: true,
        profile_img: '',
        created: serverTimestamp(),
      });

      await updateProfile(userCred.user, {
        displayName: values.name,
      });

      this.$patch({ userLoggedIn: true });
    },
    // register for admin

    async registerFromAdmin(values: RegisterValues) {
      if (!auth || !usersCollection)
        throw new Error('Firebase not initialized');

      try {
        // 1. Get the ID token of the currently logged-in admin user
        const idToken = await auth.currentUser?.getIdToken();

        if (!idToken) {
          throw new Error(
            'Authentication token not found. Ensure the user is logged in.'
          );
        }

        // 2. Send a request to the Cloud Function
        const requestOptions = {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
            Authorization: `Bearer ${idToken}`,
          },
          body: JSON.stringify(values),
        };
        const REGISTER_NEW_USER_URL = `${firebaseBase}/registerNewUser`;

        const response = await fetch(REGISTER_NEW_USER_URL, requestOptions);
        const data = await response.json();

        if (!response.ok) {
          throw new Error(data.error || 'Registration failed.');
        }

        // Use a notification or other UI method to inform the admin
        // toast.success(`New user registered with UID: ${data.uid}`);
        console.log('New user registered with UID:', data.uid);
      } catch (error) {
        // Use a notification or other UI method to display the error
        // toast.error(error.message);
        console.error('Error registering user:', error);
      }
    },

    async registerBatchFromAdmin(users: Array<RegisterValues>) {
      if (!auth || !usersCollection)
        throw new Error('Firebase not initialized');

      const results = [];

      // 1. Get the ID token of the currently logged-in admin user
      const idToken = await auth.currentUser?.getIdToken();

      if (!idToken) {
        throw new Error(
          'Authentication token not found. Ensure the user is logged in.'
        );
      }

      // Iterate over each user and attempt to register
      for (let values of users) {
        console.log('values', values);

        try {
          // 2. Send a request to the Cloud Function for each user
          const requestOptions = {
            method: 'POST',
            headers: {
              'Content-Type': 'application/json',
              Authorization: `Bearer ${idToken}`,
            },
            body: JSON.stringify(values),
          };
          const REGISTER_NEW_USER_URL = `${firebaseBase}/registerNewUser`;

          const response = await fetch(REGISTER_NEW_USER_URL, requestOptions);
          const data = await response.json();

          if (!response.ok) {
            throw new Error(data.error || 'Registration failed.');
          }

          // Log or notify success for this user
          console.log('New user registered with UID:', data.uid);
          results.push({ success: true, email: values.email, uid: data.uid });
        } catch (error) {
          const errorMessage = (error as Error).message;
          console.error('Error registering user:', errorMessage);
          results.push({
            success: false,
            email: values.email,
            message: errorMessage,
          });
        }
        await sleep(500);
      }

      // The results array will have the success status for each user
      return results;
    },

    async visitorRegister(values: RegisterValues) {
      if (!auth || !usersCollection)
        throw new Error('Firebase not initialized');

      try {
        const requestOptions = {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
          },
          body: JSON.stringify(values),
        };
        const VISITOR_REGISTER_URL = `${firebaseBase}/visitorRegister`;
        const response = await fetch(VISITOR_REGISTER_URL, requestOptions);

        const data = await response.json();

        if (!response.ok) {
          throw new Error(data.error || 'Registration failed.');
        }
      } catch (error) {
        console.error('Error registering user:', error);
      }
    },
    async adminChangePassword(email: string, newPassword: string) {
      if (!auth || !usersCollection)
        throw new Error('Firebase not initialized');

      try {
        // 1. Get the ID token of the currently logged-in admin user
        const idToken = await auth.currentUser?.getIdToken();

        if (!idToken) {
          throw new Error(
            'Authentication token not found. Ensure the user is logged in.'
          );
        }

        // Data to send
        const payload = {
          email: email,
          newPassword: newPassword,
        };

        // 2. Send a request to the Cloud Function
        const requestOptions = {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
            Authorization: `Bearer ${idToken}`,
          },
          body: JSON.stringify(payload),
        };
        const CHANGE_PASSWORD_URL = `${firebaseBase}/adminChangePassword`;
        const response = await fetch(CHANGE_PASSWORD_URL, requestOptions);
        const data = await response.json();

        if (!response.ok) {
          throw new Error(data.error || 'Password change failed.');
        }

        // Use a notification or other UI method to inform the admin
        // toast.success(`Password changed successfully for email: ${email}`);
        console.log(`Password changed successfully for email:`, email);
      } catch (error) {
        // Use a notification or other UI method to display the error
        // toast.error(error.message);
        console.error('Error changing password:', error);
      }
    },
    //Logs in a user using Firebase Authentication and initializes the listener to monitor user data changes.
    async authenticate(values: AuthenticateValues) {
      const { $firebase } = useNuxtApp();
      auth = $firebase.auth;
      usersCollection = $firebase.usersCollection;

      if (!auth || !usersCollection)
        throw new Error('Firebase not initialized');
      await signInWithEmailAndPassword(auth, values.email, values.password);
    },

    async signOut() {
      const { $firebase } = useNuxtApp();
      const auth = $firebase.auth;
      if (!auth) throw new Error('Firebase not initialized');
      if (this.unsubscribe) {
        this.unsubscribe();
        this.unsubscribe = null;
      }
      await firebaseSignOut(auth);
      await logoutSession();
      this._resetStore();
    },
  },
  getters: {
    isLoggedIn: (state: State) => state.userLoggedIn,
    currentRole: (state: State) => state.userRole,
  },
});

export default useUserStore;
