import { createIsomorphicFn } from "@tanstack/react-start";
import { getRequestHeaders } from "@tanstack/react-start/server";
import { authClient } from "@/lib/auth-client";

const CACHE_DURATION = 5 * 60 * 1000; // 5 minutes in milliseconds

interface AuthInfo {
	user: object | undefined;
	isAuthenticated: boolean;
	isUserBanned: boolean;
	banReason: string | null | undefined;
}

interface CacheEntry<T> {
	data: T;
	timestamp: number;
}

const authCache: {
	server?: CacheEntry<AuthInfo>;
	client?: CacheEntry<AuthInfo>;
} = {};

function getCachedData<T>(
	key: "server" | "client",
	cache: typeof authCache,
): T | null {
	const entry = cache[key];
	if (!entry) return null;

	const now = Date.now();
	const isExpired = now - entry.timestamp > CACHE_DURATION;

	if (isExpired) {
		delete cache[key];
		return null;
	}

	return entry.data as T;
}

function setCachedData<T>(
	key: "server" | "client",
	data: T,
	cache: typeof authCache,
): void {
	cache[key] = {
		data: data as AuthInfo,
		timestamp: Date.now(),
	};
}

const getAuthInfoInternal = createIsomorphicFn()
	.server(async () => {
		const auth = await authClient.getSession({
			fetchOptions: {
				headers: getRequestHeaders(),
			},
		});
		const isAuthenticated = typeof auth.data?.user.id === "string";

		return {
			user: auth.data?.user,
			isAuthenticated,
			isUserBanned: auth.data?.user.banned ?? false,
			banReason: auth.data?.user.banReason,
		};
	})
	.client(async () => {
		const auth = await authClient.getSession();
		const isAuthenticated = typeof auth.data?.user.id === "string";

		return {
			user: auth.data?.user,
			isAuthenticated,
			isUserBanned: auth.data?.user.banned ?? false,
			banReason: auth.data?.user.banReason,
		};
	});

export const getAuthInfo = createIsomorphicFn()
	.server(async () => {
		const cached = getCachedData<AuthInfo>("server", authCache);
		if (cached) {
			return cached;
		}

		const result = await getAuthInfoInternal();
		setCachedData("server", result, authCache);
		return result;
	})
	.client(async () => {
		const cached = getCachedData<AuthInfo>("client", authCache);
		if (cached) {
			return cached;
		}

		const result = await getAuthInfoInternal();
		setCachedData("client", result, authCache);
		return result;
	});

export const canAccessDashboard = createIsomorphicFn()
	.server(async () => {
		const hasAccess = await authClient.admin.hasPermission({
			permissions: {
				dashboard: ["access"],
			},
			fetchOptions: {
				headers: getRequestHeaders(),
			},
		});
		return hasAccess.data?.success ?? false;
	})
	.client(async () => {
		const hasAccess = await authClient.admin.hasPermission({
			permissions: {
				dashboard: ["access"],
			},
		});
		return hasAccess.data?.success ?? false;
	});
