import { paraglideMiddleware } from '$lib/paraglide/server';
import { dev } from '$app/environment';
import { VITE_BACKEND_URL } from '$env/static/private';
import { endpoints } from '$lib/utils/api';
import { redirect, type Handle, type HandleFetch } from '@sveltejs/kit';
import { jwtDecode } from 'jwt-decode';

export const handleFetch: HandleFetch = async ({ request, fetch, event }) => {
	let newRequest = request;

	const accessToken = event.cookies.get('accessToken');
	if (accessToken) {
		newRequest = new Request(request, {
			headers: {
				...request.headers,
				Authorization: `Bearer ${accessToken}`
			}
		});
	}

	let response = await fetch(newRequest);

	if (response.status === 401 && accessToken) {
		try {
			const refreshResponse = await fetch(`${VITE_BACKEND_URL}${endpoints.auth.rotateToken}`, {
				method: 'POST',
				headers: {
					'Content-Type': 'application/json',
					Authorization: `Bearer ${accessToken}`
				}
			});

			if (refreshResponse.ok) {
				const { accessToken: newAccessToken } = await refreshResponse.json();
				event.cookies.set('accessToken', newAccessToken, {
					path: '/',
					httpOnly: true,
					sameSite: 'lax',
					secure: false,
					maxAge: 300
				});

				newRequest = new Request(request, {
					headers: {
						...request.headers,
						Authorization: `Bearer ${newAccessToken}`
					}
				});
				response = await fetch(newRequest);
			} else {
				console.error('Refresh token failed:', await refreshResponse.text());
				event.cookies.delete('accessToken', { path: '/' });
				event.cookies.delete('u', { path: '/' });
			}
		} catch (error) {
			console.error('Token refresh error:', error);
			event.cookies.delete('accessToken', { path: '/' });
			event.cookies.delete('u', { path: '/' });
		}
	}

	return response;
};

const handleParaglide: Handle = async ({ event, resolve }) => {
	if (dev && event.url.pathname === '/.well-known/appspecific/com.chrome.devtools.json') {
		return new Response(undefined, { status: 404 });
	}

	const accessToken = event.cookies.get('accessToken');
	const userCookie = event.cookies.get('u');

	event.locals.authenticated = false;
	event.locals.user = null;

	const refreshTokens = async () => {
		if (!accessToken) return null;

		const response = await fetch(`${VITE_BACKEND_URL}${endpoints.auth.rotateToken}`, {
			method: 'POST',
			headers: {
				'Content-Type': 'application/json',
				Authorization: `Bearer ${accessToken}`
			}
		});

		if (!response.ok) {
			throw new Error('Failed to refresh tokens');
		}

		const { accessToken: newAccessToken, user } = await response.json();

		event.cookies.set('accessToken', newAccessToken, {
			path: '/',
			httpOnly: true,
			sameSite: 'lax',
			secure: false
		});

		if (user) {
			event.cookies.set('u', JSON.stringify(user), {
				path: '/',
				httpOnly: true,
				sameSite: 'lax',
				secure: false
			});
			return user;
		}

		return null;
	};

	try {
		if (accessToken) {
			const decodedToken: { exp: number } = jwtDecode(accessToken);
			const currentTime = Date.now() / 1000;

			if (decodedToken.exp - currentTime < 120) {
				const user = await refreshTokens();
				if (user) {
					event.locals.user = user;
				}
			}

			if (userCookie) {
				try {
					event.locals.user = JSON.parse(userCookie);
				} catch (error) {
					console.error('Invalid user cookie:', error);
					event.cookies.delete('u', { path: '/' });
				}
			}

			event.locals.authenticated = true;
		}
	} catch (error) {
		console.error('Authentication error:', error);
		event.cookies.delete('accessToken', { path: '/' });
		event.cookies.delete('u', { path: '/' });
	}

	const routeId = event.route.id;

	if (routeId?.startsWith('/(auth)')) {
		if (!event.locals.authenticated) {
			throw redirect(302, '/login');
		}
	}

	if (
		event.locals.authenticated &&
		(event.url.pathname === '/login' || event.url.pathname === '/register')
	) {
		throw redirect(303, '/');
	}

	// if (routeId?.startsWith('/(auth)')) {
	// 	response.headers.set('X-Auth-Check', 'required');
	// }

	return paraglideMiddleware(event.request, ({ request, locale }) => {
		event.request = request;

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