import { createClient } from '@supabase/supabase-js';
import { SignJWT } from 'jose';
import type { Database } from '@colectivo/types';

function requiredEnv(key: string): string {
	const value = process.env[key];
	if (!value) throw new Error(`Missing required env var: ${key}`);
	return value;
}

/**
 * Sign a GoTrue-compatible JWT for a seed user using the shared SUPABASE_JWT_SECRET.
 * This lets integration tests act as any seed user without going through Keycloak.
 */
async function signToken(userId: string): Promise<string> {
	const secret = new TextEncoder().encode(requiredEnv('SUPABASE_JWT_SECRET'));
	return new SignJWT({ role: 'authenticated' })
		.setProtectedHeader({ alg: 'HS256' })
		.setSubject(userId)
		.setAudience('authenticated')
		.setIssuedAt()
		.setExpirationTime('1h')
		.sign(secret);
}

/**
 * Create a Supabase client that authenticates as the given seed user.
 * RLS policies see auth.uid() = userId.
 *
 * Also calls `realtime.setAuth(token)` so Realtime subscriptions carry the
 * same identity — the server evaluates RLS against this JWT when deciding
 * which Postgres-changes events to forward.
 */
export async function createClientAs(userId: string) {
	const token = await signToken(userId);
	const client = createClient<Database>(
		requiredEnv('PUBLIC_SUPABASE_URL'),
		requiredEnv('PUBLIC_SUPABASE_ANON_KEY'),
		{
			global: { headers: { Authorization: `Bearer ${token}` } },
			auth: { persistSession: false, autoRefreshToken: false }
		}
	);
	// @ts-expect-error — realtime.setAuth exists at runtime on supabase-js v2
	client.realtime.setAuth(token);
	return client;
}

/**
 * Create a service-role client that bypasses RLS entirely.
 * Use only for test setup and cleanup — never in assertions.
 */
export function createAdminClient() {
	return createClient<Database>(
		requiredEnv('PUBLIC_SUPABASE_URL'),
		requiredEnv('SUPABASE_SERVICE_ROLE_KEY'),
		{ auth: { persistSession: false, autoRefreshToken: false } }
	);
}
