import React, { useEffect, useState } from "react";

import {
  createUser as registerApi,
  isLoggedIn,
  login as loginApi,
  logout as logoutApi,
} from "../api";
import { useQuery } from "../hooks";

import { useLocation, useNavigate } from "react-router-dom";

const initState = {
  user: undefined,
};

export const AuthenticationContext = React.createContext({
  ...initState,
  login: () => {},
  register: () => {},
  logout: () => {},
});

export const AuthenticationProvider = ({ children }) => {
  const navigate = useNavigate();
  const location = useLocation();
  const query = useQuery();
  const [authState, setAuthState] = useState(initState);
  const [isLoading, setIsLoading] = useState(true);

  const redirect = () => {
    navigate(query.get("redirect_uri") || "/");
  };

  const login = async (email, password) => {
    loginApi(email, password)
      .then((user) => {
        setAuthState({ user });
        redirect();
      })
      .catch(() => {
        console.error("ici ca catch fort");
        setAuthState({ user: undefined });
      });
  };

  const register = async (username, password, confirmation) => {
    registerApi(username, password, confirmation).then((user) => {
      setAuthState({ user });
      redirect();
    });
  };

  const logout = () => {
    logoutApi().then(() => {
      setAuthState(initState);
      navigate(`/login`);
    });
  };

  useEffect(() => {
    isLoggedIn()
      .then((user) => {
        if (user === "Unauthorized") throw new Error("Unauthorized");
        setAuthState({ user });
        if (location.pathname === "/login") {
          redirect();
        }
      })
      .catch(() => {
        setAuthState({ user: undefined });

        if (!location.pathname.match(/^(\/|\/login|\/register)$/)) {
          navigate(`/login?redirect_uri=${encodeURI(location.pathname)}`);
        }
      })
      .finally(() => {
        setIsLoading(false);
      });
  }, []);

  useEffect(() => {
    if (location.pathname === "/logout") {
      logout();
    }
  }, [location]);

  if (isLoading) {
    return <p>Loading...</p>;
  }

  return (
    <AuthenticationContext.Provider
      value={{ ...authState, login, logout, register }}
    >
      {children}
    </AuthenticationContext.Provider>
  );
};
