/**
 * Consulta al Hub las aplicaciones del Workspace accesibles al usuario autenticado.
 *
 * Endpoint: GET /api/v1/auth/my-apps
 * Respuesta (top-level): { routing: string, apps: [...] }
 *   - routing: decisión de routing del Hub (no se usa para redirigir; siempre se muestra el
 *     launcher para que el usuario elija).
 *   - apps: productos del Workspace accesibles, cada uno con su URL.
 *
 * Mismo patrón que la llamada a /api/v1/auth/my-tenants en +layout.server.ts.
 */

import { dev } from '$app/environment';
import { env } from '$env/dynamic/private';
import type { WorkspaceApp } from '$lib/stores/workspace-apps.svelte';

export type MyAppsResponse = {
	routing: string;
	apps: WorkspaceApp[];
};

const EMPTY_RESPONSE: MyAppsResponse = { routing: '', apps: [] };

function resolveHubUrl(): string {
	return (env.INTERNAL_HUB_URL || env.HUB_URL || 'http://localhost:8001').replace(/\/+$/, '');
}

/** Item crudo de `apps` tal como lo devuelve el Hub en /api/v1/auth/my-apps. */
type RawWorkspaceApp = {
	id?: number | string;
	name?: string;
	slug?: string;
	login_url?: string;
	sso_url?: string;
	image_url?: string | null;
	description?: string | null;
};

/** Primer valor string no vacío. */
function firstNonEmpty(...values: (string | null | undefined)[]): string | null {
	for (const value of values) {
		if (typeof value === 'string' && value.trim()) return value;
	}
	return null;
}

/** Normaliza un item crudo de `apps` (shape del Hub) a WorkspaceApp para el launcher. */
function normalizeWorkspaceApp(raw: unknown): WorkspaceApp | null {
	if (!raw || typeof raw !== 'object') return null;
	const app = raw as RawWorkspaceApp;

	// URL de entrada de la app (login_url). Para apps del mismo origin trae el `active_system`
	// que usa el launcher para el cambio de sistema local; sso_url solo como respaldo.
	const url = firstNonEmpty(app.login_url, app.sso_url);
	if (!url) return null; // sin URL la app no es accionable en el launcher

	const id = app.id != null ? String(app.id) : (firstNonEmpty(app.slug) ?? url);

	return {
		id,
		name: firstNonEmpty(app.name, app.slug) ?? id,
		slug: firstNonEmpty(app.slug),
		url,
		iconUrl: firstNonEmpty(app.image_url)
	};
}

/**
 * Obtiene las apps del Workspace usando el token del usuario.
 * Nunca lanza: ante cualquier fallo degrada a respuesta vacía para no romper el dashboard
 * (mismo criterio que la carga de tenants).
 */
export async function fetchMyApps(
	accessToken: string,
	fetch: typeof globalThis.fetch,
	tenantOverride?: string | null
): Promise<MyAppsResponse> {
	try {
		const hubUrl = resolveHubUrl();
		const res = await fetch(`${hubUrl}/api/v1/auth/my-apps`, {
			headers: {
				Authorization: `Bearer ${accessToken}`,
				...(tenantOverride ? { 'X-Tenant-Override': tenantOverride } : {})
			}
		});
		if (!res.ok) {
			if (dev) console.log(`[my-apps] Hub respondió status ${res.status} en ${hubUrl} → sin apps`);
			return EMPTY_RESPONSE;
		}

		const data = (await res.json()) as { routing?: unknown; apps?: unknown };

		const apps = Array.isArray(data.apps)
			? data.apps.map(normalizeWorkspaceApp).filter((app): app is WorkspaceApp => app !== null)
			: [];

		return {
			routing: typeof data.routing === 'string' ? data.routing : '',
			apps
		};
	} catch (error) {
		if (dev) console.log('[my-apps] error llamando al Hub:', error);
		return EMPTY_RESPONSE;
	}
}
