import { DEV_USER_ID } from "@env";
import { FirebaseAuthTypes } from "@react-native-firebase/auth";
import React, {
	createContext,
	useCallback,
	useContext,
	useEffect,
	useState,
} from "react";
import { handleSignOut, onAuthStateChanged } from "../auth";
import { useAuthHeader } from "../graphql/client";

interface AuthContextType {
	isLoggedIn: boolean;
	isLoading: boolean;
	user: FirebaseAuthTypes.User | null;
	logOut: () => Promise<void>;
}

const AuthContext = createContext<AuthContextType | undefined>(undefined);

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

	const [contextUser, setContextUser] = useState<FirebaseAuthTypes.User | null>(
		null,
	);
	const [isLoggedIn, setIsLoggedIn] = useState<boolean>(false);
	const [isLoading, setIsLoading] = useState<boolean>(true); // this is for a LoadingContext (auth, app reloads, foreground etc)

	const _completeAuthentication = useCallback(
		(
			user: FirebaseAuthTypes.User,
			token: string,
			isLoggedIn: boolean,
			tokenType: "user_id" | "Authorization" = "Authorization",
		) => {
			setAuthHeader({ key: tokenType, value: token });
			setContextUser(user);
			setIsLoggedIn(isLoggedIn);
			setIsLoading(false);
		},
		[setAuthHeader],
	);

	const authStateChangeCallback = async (user: FirebaseAuthTypes.User) => {
		if (user) {
			const token = await user.getIdToken();
			_completeAuthentication(user, token, true);
		} else {
			_completeAuthentication(undefined, undefined, false);
		}
	};

	useEffect(() => {
		let unsubscribe = () => {
			console.log("Dev Mode");
		};

		if (!DEV_USER_ID) {
			unsubscribe = onAuthStateChanged(authStateChangeCallback);
		}

		return unsubscribe;
		// eslint-disable-next-line react-hooks/exhaustive-deps
	}, []);

	useEffect(() => {
		const setAuthAsync = async () => {
			if (DEV_USER_ID) {
				console.log("Setting fake authorization user to: ", DEV_USER_ID);
				_completeAuthentication(null, DEV_USER_ID, true, "user_id");
			}
		};
		setAuthAsync();
	}, [_completeAuthentication]);

	const logOut = async () => {
		await handleSignOut();
	};

	return (
		<AuthContext.Provider
			value={{ isLoggedIn, isLoading, user: contextUser, logOut }}
		>
			{children}
		</AuthContext.Provider>
	);
};

export const useAuth = () => {
	const context = useContext(AuthContext);
	if (context === undefined) {
		throw new Error("useAuth must be used within an AuthProvider");
	}
	return context;
};
