import pkg from '@supabase/ssr';
const { createServerClient } = pkg;
import { type Handle, redirect } from '@sveltejs/kit';
import { sequence } from '@sveltejs/kit/hooks';
import { PUBLIC_SUPABASE_URL, PUBLIC_SUPABASE_ANON_KEY } from '$env/static/public';
import { env } from '$env/dynamic/private';
import type { Database } from '$lib/types/database';

// Use internal URL for server-side operations (Docker network), fallback to public URL
const SERVER_SUPABASE_URL = env.SUPABASE_INTERNAL_URL || PUBLIC_SUPABASE_URL;

/**
 * Supabase authentication hook
 * Sets up the Supabase client with cookie handling for SSR
 */
const supabaseHandle: Handle = async ({ event, resolve }) => {
	event.locals.supabase = createServerClient<Database>(
		SERVER_SUPABASE_URL,
		PUBLIC_SUPABASE_ANON_KEY,
		{
			cookies: {
				getAll: () => event.cookies.getAll(),
				setAll: (cookiesToSet) => {
					cookiesToSet.forEach(({ name, value, options }) => {
						event.cookies.set(name, value, { ...options, path: '/' });
					});
				}
			}
		}
	);

	/**
	 * Safe session getter that validates the JWT
	 * Returns session, user, and member data
	 */
	event.locals.safeGetSession = async () => {
		const {
			data: { session }
		} = await event.locals.supabase.auth.getSession();

		if (!session) {
			return { session: null, user: null, member: null };
		}

		// Validate the session by getting the user
		const {
			data: { user },
			error: userError
		} = await event.locals.supabase.auth.getUser();

		if (userError || !user) {
			return { session: null, user: null, member: null };
		}

		// Fetch member profile with dues status
		const { data: member } = await event.locals.supabase
			.from('members_with_dues')
			.select('*')
			.eq('id', user.id)
			.single();

		return { session, user, member };
	};

	return resolve(event, {
		filterSerializedResponseHeaders(name) {
			return name === 'content-range' || name === 'x-supabase-api-version';
		}
	});
};

/**
 * Authorization hook
 * Protects routes based on authentication and role requirements
 */
const authorizationHandle: Handle = async ({ event, resolve }) => {
	const { session, member } = await event.locals.safeGetSession();
	const path = event.url.pathname;

	// API routes handle their own authentication
	if (path.startsWith('/api/')) {
		return resolve(event);
	}

	// Auth callback routes should always be accessible
	if (path.startsWith('/auth/')) {
		return resolve(event);
	}

	// Logout route should always be accessible
	if (path === '/logout') {
		return resolve(event);
	}

	// Protected routes - require authentication
	const protectedPrefixes = ['/dashboard', '/profile', '/payments', '/documents', '/board', '/admin'];
	const isProtectedRoute = protectedPrefixes.some((prefix) => path.startsWith(prefix));

	if (isProtectedRoute && !session) {
		throw redirect(303, `/login?redirectTo=${encodeURIComponent(path)}`);
	}

	// Handle authenticated users without a member profile
	// This can happen if member record creation failed or was deleted
	if (isProtectedRoute && session && !member) {
		console.error('Authenticated user has no member profile:', session.user?.id);
		// Sign them out and redirect to login with an error
		await event.locals.supabase.auth.signOut();
		throw redirect(303, '/login?error=no_profile');
	}

	// Board routes - require board or admin role
	if (path.startsWith('/board') && member) {
		if (member.role !== 'board' && member.role !== 'admin') {
			throw redirect(303, '/dashboard');
		}
	}

	// Admin routes - require admin role
	if (path.startsWith('/admin') && member) {
		if (member.role !== 'admin') {
			throw redirect(303, '/dashboard');
		}
	}

	// Redirect authenticated users away from auth pages
	if (session && (path === '/login' || path === '/signup')) {
		throw redirect(303, '/dashboard');
	}

	return resolve(event);
};

export const handle: Handle = sequence(supabaseHandle, authorizationHandle);
