import { TextUtil } from "@greatness/util";
import {
  createContext,
  useCallback,
  useContext,
  useEffect,
  useState,
} from "react";
import { useLocation, useNavigate } from "react-router-dom";

import { User } from "@/api/controller/user";
import { RequestHelper } from "@/api/request";
import type { APIFieldError } from "@/api/types";
import { NavigationPath } from "@/constants/navigation";
import useOAuthQueryToken from "@/util/useOAuthQueryToken";
import JWTUtil from "@/util/JWTUtil";

export interface IUser {
  id: string;
  email: string;
  firstName: string;
  lastName: string;
  role: string;
}

interface SessionContextState {
  hasJwtStored: boolean;
  isAuthenticated: boolean;
  login: (
    email: string,
    password: string,
    rememberMe: boolean,
  ) => Promise<APIFieldError | null>;
  logout: () => boolean;
  user: IUser | null;
}

const DEFAULT_STATE: SessionContextState = {
  hasJwtStored: false,
  isAuthenticated: false,
  login: async () => null,
  logout: () => true,
  user: null,
};

const SessionContext = createContext(DEFAULT_STATE);

export const useSessionContext = (): SessionContextState => useContext(SessionContext);

export default function SessionContextProvider({
  children,
}: React.PropsWithChildren) {
  const location = useLocation();
  const navigate = useNavigate();

  const [isAuthenticated, setIsAuthenticated] = useState(true);
  const [user, setUser] = useState<IUser | null>(null);

  const { setToken, removeTokenFromQuery } = useOAuthQueryToken();

  const logout = useCallback(() => {
    setIsAuthenticated(false);
    RequestHelper.redirectToLoginPage();
    return true;
  }, []);

  const checkSession = useCallback(async () => {
    setUser({
      id: "1",
      email: "test@test.com",
      firstName: "Test",
      lastName: "Test",
      role: "admin",
    });
    return;

    const hasToken = !TextUtil.isEmpty(JWTUtil.get().accessToken);
    if (!hasToken) {
      logout();
      return;
    }
    const { response, isResponseOk } = await User.me();
    console.log("response", response);
    if (!isResponseOk) {
      logout();
      return;
    }
    // @ts-expect-error ok great
    setUser(response.user);

    if (location.pathname.endsWith(NavigationPath.Login)) {
      removeTokenFromQuery();
      navigate(NavigationPath.Home.Base);
    }
  }, [location.pathname, navigate, removeTokenFromQuery, logout]);

  const login = useCallback(
    async (email: string, password: string, rememberMe: boolean) => {
      const { response, isResponseOk } = await User.login({
        email,
        password,
        rememberMe,
      });
      if (isResponseOk) {
        setIsAuthenticated(true);
        setToken({
          // @ts-expect-error ok great
          accessToken: response.accessToken,
        });
        await checkSession();
        return null;
      }
      // @TODO types
      return response as unknown as APIFieldError;
    },
    [checkSession, setToken],
  );

  // biome-ignore lint/correctness/useExhaustiveDependencies: <explanation> great
  useEffect(() => {
    checkSession();
  }, []);

  return (
    <SessionContext.Provider
      value={{
        hasJwtStored: !TextUtil.isEmpty(JWTUtil.get().accessToken),
        isAuthenticated,
        login,
        logout,
        user,
      }}
    >
      {children}
    </SessionContext.Provider>
  );
};

