import {
	ApolloClient,
	ApolloLink,
	ApolloProvider,
	HttpLink,
	InMemoryCache,
	from,
} from "@apollo/client";

import React, {
	ReactNode,
	createContext,
	useContext,
	useMemo,
	useState,
} from "react";

import { API_URI } from "@env";

type Props = {
	children: ReactNode;
};

export const AuthHeaderContext = createContext<
	| {
			authHeader: { key: string; value: string };
			setAuthHeader: React.Dispatch<
				React.SetStateAction<{ key: string; value: string }>
			>;
	  }
	| undefined
>(undefined);

// Hook to use the auth header context
export const useAuthHeader = () => {
	const context = useContext(AuthHeaderContext);
	if (!context) {
		throw new Error("useAuthHeader must be used within a ClientProvider");
	}
	return context;
};

export const ClientProvider: React.FC<Props> = ({ children }) => {
	const [authHeader, setAuthHeader] = useState({ key: "", value: "" });
	console.log(`The api uri is ${API_URI}`);
	const httpLink = new HttpLink({
		uri: API_URI,
	});
	const cache = new InMemoryCache({});

	const authMiddleware = new ApolloLink((operation, forward) => {
		const { key, value } = authHeader;
		if (key && value) {
			operation.setContext({
				headers: {
					[key]: value,
				},
			});
		}

		return forward(operation);
	});

	// We use useMemo to avoid recreating the client on every render
	const client = useMemo(
		() =>
			new ApolloClient({
				// Chain the middleware with the httpLink
				link: from([authMiddleware, httpLink]),
				cache: new InMemoryCache(),
			}),
		[authHeader],
	);

	return (
		<AuthHeaderContext.Provider value={{ authHeader, setAuthHeader }}>
			<ApolloProvider client={client}>{children}</ApolloProvider>
		</AuthHeaderContext.Provider>
	);
};
