import React, { useContext, useEffect, useState } from 'react';
import auth from '../../services/auth';

const UserContext = React.createContext();

export const UserProvider = ({ children }) => {
  const [fetching, setFetching] = useState(false);
  const [token, setToken] = useState(null);
  const [error, setError] = useState(null);

  useEffect(() => {
    if (!sessionStorage) return;
    const token = JSON.parse(sessionStorage.getItem("token"));
    if (!token) return;
    const { accessToken: { jwtToken }} = token;
    const verifyToken = async (accessToken) => {
      const result = await auth.verify(accessToken);
      if (result.authenticated) {
        setToken(token);
      } else {
        await signOut();
      }
    };
    verifyToken(jwtToken);
    return () => {};
  }, []);
 
  const signIn = async (username, password) => {
    try {
      if (!username) throw new Error('Email is required');
      if (!password) throw new Error('Password is required');
  
      setFetching(true);
      setError(null);
  
      const result = await auth.signIn(username, password);

      if (result.message) throw new Error(result.message);
      signedIn(result);
    }
    catch (error) {
      setError(error.message);
    }
    finally {
      setFetching(false);
    }
  };

  const signUp = async (username, password, confirmPassword) => {
    try {
      if (!username) throw new Error('Email is required');
      if (!password) throw new Error('Password is required');
      if (password !== confirmPassword) throw new Error('Passwords do not match');

      setFetching(true);
      setError(null);

      const result = await auth.signUp(username, password);
      if (result.message) throw new Error(result.message);
    }
    catch (error) {
      setError(error.message);
    }
    finally {
      setFetching(false);
    }
  };

  const signOut = async () => {
    setToken(null);
    if (!sessionStorage) return;
    sessionStorage.removeItem("token");
  };

  const signedIn = (token) => {
    setToken(token);
    if (!sessionStorage || !token || !token.accessToken) return;
    sessionStorage.setItem("token", JSON.stringify(token));
  }

  return (
    <UserContext.Provider value={{
      fetching,
      token,
      error,
      setError,
      signIn,
      signUp,
      signOut,
    }}>
      {children}
    </UserContext.Provider>
  );
};

export const useUserContext = () => useContext(UserContext);
