/**
 * SSO auto-login page for Anexo76.
 * The Hub App Launcher redirects here with ?relay=<token> after generating a relay token.
 * This server-side load function exchanges the relay token for KC tokens via the
 * Hub backend, sets HttpOnly cookies, and redirects to /dashboard.
 */
import { redirect } from '@sveltejs/kit';
import type { PageServerLoad } from './$types';
import { setAccessTokenCookies } from '$lib/server/access-token-cookie';

// Disable client-side rendering to prevent SvelteKit from making a second
// __data.json request that would consume the one-time relay token twice.
export const csr = false;

export const load: PageServerLoad = async ({ url, cookies }) => {
	const relayToken = url.searchParams.get('relay');
	console.log('[SSO] relay token presente:', !!relayToken);

	if (!relayToken) {
		throw redirect(303, '/login?error=sso_missing_token');
	}

	// Limpiar sesión anterior para que el nuevo usuario reciba sus propias cookies.
	// No se omite el exchange aunque haya token existente — la sesión podría ser
	// de otro usuario (ej: juan que hace logout e ingresa como lal17).
	// La única excepción es si el relay token ya fue consumido (lo maneja el error handler).
	{
		const { clearAccessTokenCookies } = await import('$lib/server/access-token-cookie');
		clearAccessTokenCookies(cookies);
		cookies.delete('refresh_token', { path: '/' });
		cookies.delete('active_company_id', { path: '/' });
	}

	// SSO exchange must call the Hub that GENERATED the relay token.
	// This fetch runs server-side (inside the Docker container), so we must use
	// INTERNAL_HUB_URL (host.docker.internal) when available — "localhost" inside
	// a container never reaches the host where the workspace Hub is running.
	const hubUrl = (
		process.env.INTERNAL_HUB_URL ||
		process.env.HUB_URL ||
		process.env.VITE_HUB_URL ||
		'http://localhost:8001'
	).replace(/\/+$/, '');
	const baseUrl = `${hubUrl}/`;

	let response: Response;
	try {
		response = await fetch(`${baseUrl}api/v1/auth/sso-exchange`, {
			method: 'POST',
			headers: { 'Content-Type': 'application/json' },
			body: JSON.stringify({ relay_token: relayToken }),
		});
	} catch (err) {
		throw redirect(303, '/login?error=sso_hub_unreachable');
	}

	if (!response.ok) {
		const body = await response.json().catch(() => ({}));
		const detail: string = body?.detail || 'sso_exchange_failed';
		console.error('[SSO] exchange falló:', response.status, detail);

		// If the token is "invalid/used", a concurrent request may have already
		// succeeded and set cookies. Redirect to /dashboard — if the session is
		// valid it will load; if not, the dashboard layout will redirect to /login.
		const tokenAlreadyUsed =
			detail.toLowerCase().includes('inválido') ||
			detail.toLowerCase().includes('invalido') ||
			detail.toLowerCase().includes('invalid') ||
			detail.toLowerCase().includes('used') ||
			detail.toLowerCase().includes('expired');
		if (tokenAlreadyUsed) {
			throw redirect(303, '/dashboard');
		}

		throw redirect(303, `/login?error=${encodeURIComponent(detail)}`);
	}

	const tokens = await response.json();
	console.log('[SSO] exchange exitoso, tokens recibidos:', {
		hasAccessToken: !!tokens.access_token,
		accessTokenLen: tokens.access_token?.length,
		hasRefreshToken: !!tokens.refresh_token,
		tenant_id: tokens.tenant_id,
		tenant_slug: tokens.tenant_slug,
	});

	const isProduction = process.env.NODE_ENV === 'production';
	console.log('[SSO] NODE_ENV:', process.env.NODE_ENV, '→ isProduction:', isProduction);

	// access_token — NO HttpOnly (Bearer desde JS); fragmentado si el JWT supera ~4KB
	setAccessTokenCookies(cookies, tokens.access_token, {
		secure: isProduction,
		maxAge: 60 * 60 * 24 * 7,
	});

	// refresh_token — HttpOnly (never exposed to JS)
	if (tokens.refresh_token) {
		cookies.set('refresh_token', tokens.refresh_token, {
			path: '/',
			httpOnly: true,
			secure: isProduction,
			sameSite: 'lax',
			maxAge: 60 * 60 * 24 * 30,
		});
	}

	// sso_tenant_id — HttpOnly cookie con el tenant seleccionado.
	// El backend lo pasa como X-Tenant-Override en Hub /auth/me para que
	// devuelva el tenant correcto aunque el KC token tenga otro tenant baked in.
	if (tokens.tenant_id) {
		cookies.set('sso_tenant_id', String(tokens.tenant_id), {
			path: '/',
			httpOnly: true,
			secure: isProduction,
			sameSite: 'lax',
			maxAge: 60 * 60 * 24 * 7,
		});
		// sso_tenant_pub — companion no-HttpOnly para que el cliente JS pueda
		// leer el tenant override e incluirlo como X-Tenant-Override en fetch directo al backend.
		// No es un secreto (solo un ID numérico; Hub valida UserTenant en cada request).
		cookies.set('sso_tenant_pub', String(tokens.tenant_id), {
			path: '/',
			httpOnly: false,
			secure: isProduction,
			sameSite: 'lax',
			maxAge: 60 * 60 * 24 * 7,
		});
	}
	console.log('[SSO] cookies configuradas, redirigiendo a /dashboard');

	// Ejecutar lazy-link server-side: crear UserTenant si hay invite pendiente.
	// Se llama con el Bearer token recién obtenido. Best-effort, no bloquea el SSO.
	try {
		const internalApiUrl = (
			process.env.INTERNAL_API_URL ||
			process.env.VITE_API_URL ||
			'http://backend:8000/api/'
		).replace(/\/+$/, '');
		await fetch(`${internalApiUrl}/v1/auth/lazy-link`, {
			method: 'POST',
			headers: {
				'Authorization': `Bearer ${tokens.access_token}`,
				'Content-Type': 'application/json',
			},
		}).catch(() => {});
	} catch { /* non-blocking */ }

	throw redirect(303, '/dashboard');
};
