import { createContext, FC, ReactNode, useEffect, useMemo, useState, useContext } from 'react';
import PropTypes from 'prop-types';
import { IUserProps } from '../common/data/userDummyData';
import axios from 'axios';
import { TSignInWOPasswordForm, TSignUpForm } from '../type/auth-form-type';
import { Apis } from '../constants/Apis';
import { TUser } from '../type/user-type';
import { useNavigate } from 'react-router-dom';


export interface AuthPropsOld {
	user: string;
	setUser?(...args: unknown[]): unknown;
	userData: Partial<IUserProps>;
}

interface IAuthContextProps  {
  token: string | null;
  userData: TUser | null,
  username: string | null,
  user: string;
	setUser?(...args: unknown[]): unknown;
  authState?: {token: string | null; isAuthenticated: boolean| null};
  setUserData?(...args: unknown[]): unknown;
  setUsername?: (payload: string) => void;
  onRegister?: (payload: TSignUpForm) => Promise<any>;
  onLogin?: (payload: TSignInWOPasswordForm) => Promise<any>;
  onLogout?: () => void;
}

const TOKEN_KEY = 'jwt-token';
const USER_OBJ = 'userdata';
const USERNAME = 'username';

const AuthContext = createContext<IAuthContextProps>({} as IAuthContextProps);

// This hook can be used to access the user info.
export const useAuth = () => {
  return useContext(AuthContext);
}

interface IAuthContextProviderProps {
	children: ReactNode;
}

export const AuthContextProvider: FC<IAuthContextProviderProps> = ({ children }) => {

  const navigate = useNavigate();

  const [user, setUser] = useState<string>(localStorage.getItem('facit_authUsername') || '');

	// @ts-ignore
  const [token, setToken] = useState<string | null>('');
	const [userData, setUserData] = useState(null);
  const [username, setUsername] = useState<string | null>('');
  
	const [authState, setAuthState] = useState<{token: string | null; isAuthenticated: boolean | null;}>({
    token: null,
    isAuthenticated: false
  });

  useEffect(() => {
		localStorage.setItem('facit_authUsername', user);
	}, [user]);

	useEffect(() => {
		const loadStates = async () => {
      const token = localStorage.getItem(TOKEN_KEY);
      const userObj = localStorage.getItem(USER_OBJ);
      const username = localStorage.getItem(USERNAME);
      console.log('Token stored: ', token);
      alert(token)

      if (token && userObj) {
        axios.defaults.headers.common['Authorization'] = `Bearer ${token}`;
        setAuthState({ token: token, isAuthenticated: true, });
        setUserData(JSON.parse(userObj));
        setToken(token)

        if (username) {
          await setUsername(username);
        }
        console.log('From auth context: ' + authState.isAuthenticated)

      }

      
    }

    loadStates();
	}, []);

  const setTheUsername = (username: string) => {
    // 1.a set Username state
    setUsername(username);

    // 2.b Store the username in the local storage
    localStorage.setItem(USERNAME, username);
  };
	
	const register = async (payload: TSignUpForm) => {
    try {
      const regresult = await axios.post(`${Apis.DATABASE_API_URL}/auth/registerWithoutPassword`, payload)
      console.log(regresult.data)
      return regresult.data;
    } catch (e) {
      return {error: true, msg: (e as any).response.data.message.text}
    }
  };

  const login = async (payload: TSignInWOPasswordForm) => {
    try {
      
      const result = await axios.post(`${Apis.DATABASE_API_URL}/auth/loginWithoutPassword`, payload);
      console.log(result.data);

			if (result.data.success){

        // 1. Set User obj
				setUserData(result.data.data.user);

        // 1.b Store the token in the local storage
				localStorage.setItem(USER_OBJ, JSON.stringify(result.data.data.user));

        // 2.a set token
        setToken(result.data.data.token_data.access_token);

				// 2.b Store the token in the local storage
				localStorage.setItem(TOKEN_KEY, result.data.data.token_data.access_token);

				// 3. Set the token on the header of all the request to prove that user is authenticated
				axios.defaults.headers.common['Authorization'] = `Bearer ${result.data.data.token_data.access_token}`;
			}

      return result.data;
    
    } catch (e) {
      console.log(e)
      return {error: true, msg: (e as any).response.data.msg}
    }
  };

  const logout = async () => {

    // 1. Reset User
    setUserData(null);

    // 1.b Delete token from storage
    localStorage.removeItem(USER_OBJ);

    // 2.a Reset token
    setToken("");

    // 2.b Delete token from storage
    localStorage.removeItem(TOKEN_KEY);

    // 3. Update HTTP Headers <Route element={<RequireAuth />}>
    axios.defaults.headers.common['Authorization'] = '';

    // 4.a Reset Username
    setUsername('');

    // 4.b Delete username frm storage
    localStorage.removeItem(USERNAME);

    // 5. Navigate to login page
    navigate(`/auth/sign-in`);

  };

	const value = useMemo(
		() => ({
      token,
      userData,
      username,
      user,
      setUser,
			authState,
      setUsername: setTheUsername,
			onRegister: register,
			onLogin: login,
			onLogout: logout,
		}),
		[token, userData],
	);
  

	return <AuthContext.Provider value={value}>
    {children}
  </AuthContext.Provider>;

};

AuthContextProvider.propTypes = {
	children: PropTypes.node.isRequired,
};

export default AuthContext;
