import React, { createContext, useContext, useState, useEffect } from 'react';
import Cookies from 'js-cookie';
import { checkSession } from '@/functions/auth/checkSession';
import { saveSession } from '@/functions/auth/saveSession';
import UserProps from '@/interfaces/User';
import { decrypt } from '@/functions/system/decrypt';

interface AuthContextProps {
  user: UserProps | null;
  status: 'loading' | 'authenticated' | 'unauthenticated';
  refreshSession: () => Promise<void>;
}

const AuthContext = createContext<AuthContextProps>(null!);

let lastExecutionTime = 0;

export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {

  const [user, setUser] = useState<any | null>(null);
  const [status, setStatus] = useState<'loading' | 'authenticated' | 'unauthenticated'>('loading');

  const refreshSession = async () => {
    await checkSession({
      user: {
        set: setUser,
        value: user
      },
      status: {
        set: setStatus,
        value: status
      }
    });
  }

  const handleFocus = async () => {
    const currentTime = Date.now();
    const timeSinceLastExecution = currentTime - lastExecutionTime;

    // If less than 1 minute has passed since the last execution, skip the function
    if (timeSinceLastExecution < 60000) {
      return;
    } else {
      lastExecutionTime = currentTime;

      await refreshSession();
    }
  };

  async function checkUser() {
    try {
      const cookieSession = Cookies.get('ultima-auth-session');
      const storageSessionUser = localStorage.getItem('ultima-auth-jwt-session');
      if (storageSessionUser &&  cookieSession) {
        try {
          const parsedSession = JSON.parse(cookieSession);
          const jsonSessionUser: any = await decrypt(parsedSession.userId, storageSessionUser);
          if (jsonSessionUser) {
            setUser({ ...jsonSessionUser });
            setStatus('authenticated');
          }
        } catch (error) {
          console.error(error);
          // localStorage.removeItem('ultima-auth-jwt-session');
        }
      }
      return;
    } catch (error) {
      console.error(error);
      setTimeout(checkUser, 500);
    };
  };

  useEffect(() => {
    
    // Handle token from redirect (mobile)
    const handleRedirectCallback = () => {
      const urlParams = new URLSearchParams(window.location.search);
      const tokens = urlParams.get('tokens');
      const authError = urlParams.get('authError');
      if (authError) {
        new Notification('Authentication Error', {
            body: 'There was an error authenticating your account. Please try again later.'
        });
      } else if (tokens) {
        const parsedTokens = JSON.parse(decodeURIComponent(tokens));

        saveSession(parsedTokens);
        setStatus('authenticated');
      }
    };

    handleRedirectCallback();
    checkUser();
    handleFocus();

    window.addEventListener('visibilitychange', handleFocus);
    window.addEventListener('ultimaCheckSession', refreshSession);

    return () => {
      window.removeEventListener('visibilitychange', handleFocus);
      window.removeEventListener('ultimaCheckSession', refreshSession);
    };
  }, []);

  return (
    <AuthContext.Provider value={{
      user,
      status,
      refreshSession
    }}>
      {children}
    </AuthContext.Provider>
  );
};

export const useSession = () => {
  const context: AuthContextProps = useContext(AuthContext);

  if (context === null) {
    throw new Error('useSession must be used within an AuthProvider');
  }

  return context;
};
