<script lang="ts">
	import { setContext, onMount, onDestroy } from 'svelte';
	import { invalidateAll, goto } from '$app/navigation';
	import type { LayoutData } from './$types';
	import AppSidebar from '$lib/components/sidebar/app-sidebar.svelte';
	import * as Breadcrumb from '$lib/components/ui/breadcrumb/index.js';
	import { Separator } from '$lib/components/ui/separator/index.js';
	import * as Sidebar from '$lib/components/ui/sidebar/index.js';
	import { companyStore } from '$lib/stores/company.svelte';
	import ExchangeRateGuard from '$lib/components/dashboard/exchange_rate/exchange-rate-guard.svelte';
	import SessionTimeoutWarning from '$lib/components/session-timeout-warning.svelte';
	import { page } from '$app/state';
	import { browser } from '$app/environment';
	import { CSV_IMPORT_SESSION_CHANGED, readCsvImportSession } from '$lib/csv-import-session';
	import {
		createSessionManager,
		destroySessionManager,
		SESSION_EXPIRED_EVENT
	} from '$lib/session-manager';
	import type { SessionExpiredDetail } from '$lib/session-manager';
	import { authStore } from '$lib/auth';
	import { logout, getKeycloakInstance } from '$lib/auth';
	import LicenseErrorScreen from '$lib/components/license-error-screen.svelte';

	type LicenseError = { type: string; message: string; status: number };
	let { data, children }: { data: LayoutData & { licenseError?: LicenseError }; children: any } = $props();

	let csvImportBanner = $state(false);
	let csvImportBannerLabel = $state<string | null>(null);

	function updateCsvImportBanner() {
		if (!browser) {
			csvImportBanner = false;
			csvImportBannerLabel = null;
			return;
		}
		const path = page.url.pathname;
		const cid = companyStore.activeCompany?.id;
		if (path.includes('/dashboard/csv-upload')) {
			csvImportBanner = false;
			csvImportBannerLabel = null;
			return;
		}
		const session = readCsvImportSession(cid);
		csvImportBanner = session != null;
		const raw = session?.label;
		csvImportBannerLabel = typeof raw === 'string' && raw.trim() ? raw.trim() : null;
	}

	$effect(() => {
		if (!browser) return;
		page.url.pathname;
		companyStore.activeCompany?.id;
		updateCsvImportBanner();
	});

	// Hacer disponible el usuario en el contexto para los componentes hijos.
	// El sidebar ya lee de page.data directamente; este contexto lo usan otros componentes.
	setContext('user', data.user);
	setContext('userTenants', data.userTenants ?? []);
	// Actualizar el contexto reactive al cambiar data.user (post invalidateAll)
	$effect(() => { setContext('user', data.user); });

	// ── Manejar expiración de sesión ────────────────────────────────────────
	function handleSessionExpired(e: Event) {
		const { reason } = (e as CustomEvent<SessionExpiredDetail>).detail;
		console.info(`[Dashboard] Sesión expirada (motivo: ${reason}) — cerrando sesión`);
		void logout();
	}

	onMount(() => {
		// ── Inicializar el token en el authStore desde los datos del servidor ──
		// El servidor valida la cookie y pasa el access_token a través de data.user.token.
		// Lo almacenamos en memoria (authStore) sin tocar localStorage.
		if (data.user?.token) {
			authStore.setToken(data.user.token);
			authStore.setAuthenticated(true);
		}

		if (data.user) {
			const resolvedAvatarUrl =
				data.user.workspaceAvatarUrl ||
				data.user.workspace_avatar_url ||
				data.user.avatarUrl ||
				data.user.avatar_url ||
				data.user.legacyAvatarUrl ||
				data.user.legacy_avatar_url ||
				null;
			authStore.setUser({
				id: data.user.sub ?? data.user.id ?? '',
				username: data.user.preferred_username ?? data.user.username ?? '',
				email: data.user.email,
				name: data.user.name,
				avatarUrl: resolvedAvatarUrl,
				workspaceAvatarUrl: data.user.workspaceAvatarUrl ?? data.user.workspace_avatar_url ?? null,
				legacyAvatarUrl: data.user.legacyAvatarUrl ?? data.user.legacy_avatar_url ?? data.user.avatar_url ?? null,
				tenantId: data.user.tenant_id,
				roles: data.user.roles ?? [],
				permissions: data.user.permissions ?? []
			});
		}

		// ── Inicializar el SessionManager ─────────────────────────────────────
		if (data.user?.token) {
			const mgr = createSessionManager({
				refreshBeforeExpirySeconds: 60,      // Refrescar 60s antes de que expire
				idleTimeoutMs: 30 * 60 * 1000,       // Idle timeout: 30 minutos
				warningBeforeIdleMs: 5 * 60 * 1000,  // Advertencia: 5 min antes del idle
				ssoCheckIntervalMs: 5 * 60 * 1000,   // Verificar sesión SSO cada 5 min
				getKeycloakInstance,
				onTokenRefreshed: (newToken) => {
					authStore.setToken(newToken);
				},
				onSessionExpired: (reason) => {
					void logout();
				}
			});

			mgr.start(data.user.token);
		}

		// ── Escuchar evento global de expiración de sesión ────────────────────
		window.addEventListener(SESSION_EXPIRED_EVENT, handleSessionExpired);

		// ── Inicializar compañías ─────────────────────────────────────────────
		if (data.companies) {
			const activeCompanyId = (data as { activeCompanyId?: number }).activeCompanyId;
			void (async () => {
				await companyStore.initialize(data.companies, activeCompanyId);
				// Releer en cliente: el SSR puede haber quedado desfasado respecto al provisionamiento.
				await companyStore.loadCompanies(undefined, activeCompanyId);
			})();
		}

		// ── Escuchar cambios de compañía y recargar datos ─────────────────────
		const handleCompanyChange = async () => {
			await invalidateAll();
			await goto(`${page.url.pathname}${page.url.search}${page.url.hash}`, { invalidateAll: true });
		};
		window.addEventListener('companyChanged', handleCompanyChange);
		window.addEventListener(CSV_IMPORT_SESSION_CHANGED, updateCsvImportBanner);
		updateCsvImportBanner();

		return () => {
			window.removeEventListener('companyChanged', handleCompanyChange);
			window.removeEventListener(CSV_IMPORT_SESSION_CHANGED, updateCsvImportBanner);
			window.removeEventListener(SESSION_EXPIRED_EVENT, handleSessionExpired);
		};
	});

	onDestroy(() => {
		destroySessionManager();
	});
</script>

{#if data.licenseError}
	<LicenseErrorScreen error={data.licenseError} />
{:else}
<Sidebar.Provider>
	<AppSidebar />
	<Sidebar.Inset class="overflow-x-hidden">
		<header
			class="flex h-16 shrink-0 items-center gap-2 transition-[width,height] ease-linear group-has-data-[collapsible=icon]/sidebar-wrapper:h-12"
		>
			<div class="flex items-center gap-2 px-4">
				<Sidebar.Trigger class="-ml-1" />
				<Separator orientation="vertical" class="mr-2 data-[orientation=vertical]:h-4" />
				<!--
				<Breadcrumb.Root>
					<Breadcrumb.List>
						<Breadcrumb.Item class="hidden md:block">
							<Breadcrumb.Link href="/dashboard">Dashboard</Breadcrumb.Link>
						</Breadcrumb.Item>
						<Breadcrumb.Separator class="hidden md:block" />
						<Breadcrumb.Item>
							<Breadcrumb.Page>Inicio</Breadcrumb.Page>
						</Breadcrumb.Item>
					</Breadcrumb.List>
				</Breadcrumb.Root>
				-->
			</div>
		</header>
		<div
			id="dashboard-main-content"
			class="flex flex-1 flex-col min-h-0 gap-4 overflow-y-auto overflow-x-hidden p-4 pt-0"
		>
			{#if csvImportBanner}
				<a
					href="/dashboard/csv-upload"
					class="flex flex-wrap items-center justify-between gap-2 rounded-lg border border-primary/25 bg-primary/5 px-4 py-2.5 text-sm text-foreground shadow-sm transition-colors hover:bg-primary/10"
				>
					<span>
						{#if csvImportBannerLabel}
							Importación CSV en curso: {csvImportBannerLabel}.
						{:else}
							Importación CSV en curso para esta empresa.
						{/if}
					</span>
					<span class="font-semibold text-primary">Ir a importación masiva</span>
				</a>
			{/if}
			<!-- Contenido de cada página -->
			{@render children?.()}
		</div>
	</Sidebar.Inset>
</Sidebar.Provider>

{#if !page.url.pathname.includes('/dashboard/invoices') && !page.url.pathname.includes('/dashboard/pedimentos')}
	<ExchangeRateGuard overlayClass="bg-black/5" />
{/if}

<!-- Diálogo de advertencia de sesión por inactividad -->
<SessionTimeoutWarning />
{/if}
