/**
 * MI Access Control — validates caller access to a space before
 * serving MI data (knowledge index, memory, query-content).
 *
 * Reuses existing auth primitives from spaces.ts / community-store.
 */

import { resolveCallerRole } from "./spaces";
import type { SpaceRoleString } from "./spaces";
import { loadCommunity, getDocumentData } from "./community-store";
import type { EncryptIDClaims } from "./auth";

export interface MiAccessResult {
	allowed: boolean;
	role: SpaceRoleString;
	reason?: string;
}

/**
 * Check whether the caller (identified by claims) may access MI for
 * the given space. Returns the effective role if allowed.
 */
export async function validateMiSpaceAccess(
	space: string,
	claims: EncryptIDClaims | null,
	minRole: SpaceRoleString = "viewer",
): Promise<MiAccessResult> {
	if (!space) {
		return { allowed: false, role: "viewer", reason: "Space parameter required" };
	}

	await loadCommunity(space);
	const data = getDocumentData(space);
	if (!data) {
		return { allowed: false, role: "viewer", reason: "Space not found" };
	}

	const visibility = data.meta?.visibility || "public";

	// Private and permissioned spaces require authentication
	if ((visibility === "private" || visibility === "permissioned") && !claims) {
		return { allowed: false, role: "viewer", reason: "Authentication required for this space" };
	}

	// Resolve the caller's role
	const resolved = await resolveCallerRole(space, claims);
	const role: SpaceRoleString = resolved?.role || "viewer";

	// For private spaces, non-members (viewer default) are denied
	if (visibility === "private" && role === "viewer" && !resolved?.isOwner) {
		// Check if the caller is actually a member
		if (!claims) {
			return { allowed: false, role: "viewer", reason: "Authentication required for this space" };
		}
		// resolveCallerRole returns viewer for non-members — check membership explicitly
		const callerDid = (claims.did as string) || `did:key:${(claims.sub as string).slice(0, 32)}`;
		const isMember = data.members?.[claims.sub] || data.members?.[callerDid];
		const isOwner = data.meta?.ownerDID === claims.sub || data.meta?.ownerDID === callerDid;
		if (!isMember && !isOwner) {
			return { allowed: false, role: "viewer", reason: "You don't have access to this space" };
		}
	}

	return { allowed: true, role };
}
