import { redirect, type Handle, type HandleFetch } from '@sveltejs/kit';
import { paraglideMiddleware } from '$lib/paraglide/server';
import { sequence } from '@sveltejs/kit/hooks';
import { env } from 'process';
import { cookieName, cookieMaxAge } from '$lib/paraglide/runtime';
import { detectLocale } from '$lib/shared/server/locale';

const PUBLIC_PATHS = ['/login', '/logout', '/forgot-password', '/reset-password', '/register'];

const handleLocaleDetection: Handle = ({ event, resolve }) => {
	if (!event.cookies.get(cookieName)) {
		const locale = detectLocale(event.request.headers.get('accept-language') ?? '');
		if (locale) {
			event.cookies.set(cookieName, locale, {
				path: '/',
				sameSite: 'lax',
				maxAge: cookieMaxAge,
				httpOnly: false
			});
		}
	}
	return resolve(event);
};

const handleAuth: Handle = async ({ event, resolve }) => {
	const isPublic = PUBLIC_PATHS.some((p) => event.url.pathname.startsWith(p));
	if (!isPublic && !event.locals.user) {
		throw redirect(302, '/login');
	}
	return resolve(event);
};

const handleParaglide: Handle = ({ event, resolve }) =>
	paraglideMiddleware(event.request, ({ request, locale }) => {
		event.request = request;

		return resolve(event, {
			transformPageChunk: ({ html }) => html.replace('%paraglide.lang%', locale)
		});
	});

const userGroup: Handle = async ({ event, resolve }) => {
	const auth = event.cookies.get('auth_token');

	if (auth) {
		try {
			const apiUrl = env.API_INTERNAL_URL || 'http://localhost:8080';
			const response = await fetch(`${apiUrl}/api/users/me`, {
				headers: { Authorization: auth }
			});
			if (response.ok) {
				const user = await response.json();
				event.locals.user = user;
			}
		} catch (error) {
			console.error('Error fetching user in hook:', error);
		}
	}

	return resolve(event);
};

export const handleFetch: HandleFetch = async ({ event, request, fetch }) => {
	const apiUrl = env.API_INTERNAL_URL || 'http://localhost:8080';
	const isApi = request.url.startsWith(apiUrl) || request.url.includes('/api/');

	if (isApi) {
		// If the request already carries an explicit Authorization header (e.g. the
		// login action sends Basic auth), pass it through unchanged.
		if (request.headers.has('Authorization')) {
			return fetch(request);
		}

		// Password reset endpoints are public — no auth header needed.
		const PUBLIC_API_PATHS = [
			'/api/auth/forgot-password',
			'/api/auth/reset-password',
			'/api/auth/invite/',
			'/api/auth/register'
		];
		if (PUBLIC_API_PATHS.some((p) => request.url.includes(p))) {
			return fetch(request);
		}

		const token = event.cookies.get('auth_token');

		if (!token) {
			return new Response('Unauthorized', { status: 401 });
		}

		// Clone the request first to preserve the body
		const clonedRequest = request.clone();

		// Create new request with Authorization header and preserved body
		const modifiedRequest = new Request(clonedRequest, {
			headers: {
				...Object.fromEntries(clonedRequest.headers),
				Authorization: token
			}
		});

		return fetch(modifiedRequest);
	}

	return fetch(request);
};

export const handle = sequence(userGroup, handleAuth, handleLocaleDetection, handleParaglide);
