import { Role } from "@/types/types";

type PermissionResult<T extends Record<string, readonly string[]>> = {
	[K in keyof T]: {
		[A in T[K][number]]: boolean;
	} & { all: boolean }; // Per-resource 'all'
} & { all: boolean }; // Global 'all'

// hasPermissions function with 'all' flags
export default function hasPermissions<
	T extends Record<string, readonly string[]>,
>(roles: Role[], permissions: T): PermissionResult<T> {
	// Build permissions set
	const permissionsSet: Map<string, null> = new Map();
	for (const role of roles) {
		if (!role.permissions) continue;
		for (const perm of role.permissions) {
			const key = `${perm.resource}:${perm.action}`;
			permissionsSet.set(key, null);
		}
	}

	// Build result
	const result = { all: true } as PermissionResult<T>; // Initialize global 'all' as true
	let globalAll = true; // Track global state

	for (const resource in permissions) {
		const actions = permissions[resource];
		let resourceAll = true; // Track per-resource state

		result[resource] = { all: true } as any; // Initialize resource object
		for (const action of actions) {
			const hasPerm = permissionsSet.has(`${resource}:${action}`);
			(result[resource] as Record<string, boolean>)[action] = hasPerm;
			resourceAll = resourceAll && hasPerm; // Update resource 'all'
		}
		result[resource].all = resourceAll; // Set resource 'all'
		globalAll = globalAll && resourceAll; // Update global 'all'
	}

	result.all = globalAll; // Set global 'all'
	return result as PermissionResult<T>;
}
