<script lang="ts">
	import { onMount, tick } from 'svelte';
	import { deleteService } from '$lib/api';
	import ServiceCard from '$lib/components/ServiceCard.svelte';
	import AddServiceModal from '$lib/components/AddServiceModal.svelte';
	import ActivityLog from '$lib/components/ActivityLog.svelte';
	import { subscribeHeartbeats } from '$lib/realtime';
	import type { Service, Heartbeat } from '$lib/types';

	import type { InitialLogEntry } from './+page.ts';

	let { data } = $props<{
		data: { services: (Service & { heartbeats: Heartbeat[] })[]; error: string; initialLog: InitialLogEntry[] };
	}>();

	let initialized = $state(false);
	let services = $state<(Service & { heartbeats: Heartbeat[] })[]>([]);
	let error = $state('');
	let showModal = $state(false);

	let isKiosk = $state(false);
	let kioskFloating = $state(false);
	let kioskTimer: ReturnType<typeof setTimeout> | undefined;
	let wakeLock: WakeLockSentinel | null = $state(null);
	let pulseId = $state(0);

	$effect(() => {
		if (!initialized && data) {
			services = [...data.services];
			error = data.error;
			initialized = true;
		}
	});

	interface LogEntry {
		kind: 'check' | 'created' | 'deleted' | 'transition';
		serviceName: string;
		serviceUrl: string;
		timestamp: Date;
		hb?: Heartbeat;
		wasUp?: boolean;
	}

	let logEntries = $state<LogEntry[]>([]);

	$effect(() => {
		if (data?.initialLog && logEntries.length === 0) {
			logEntries = data.initialLog.map((e) => ({ ...e, timestamp: new Date(e.timestamp) }));
		}
	});

	function pushEntry(entry: LogEntry) {
		logEntries = [...logEntries, entry];
		if (logEntries.length > 200) {
			logEntries = logEntries.slice(-150);
		}
	}

	function handleCreated(svc: Service) {
		services = [{ ...svc, heartbeats: [] }, ...services];
		pushEntry({
			kind: 'created',
			serviceName: svc.name,
			serviceUrl: svc.url,
			timestamp: new Date()
		});
	}

	async function handleDeleted(id: number) {
		const svc = services.find((s) => s.id === id);
		try {
			await deleteService(id);
			services = services.filter((s) => s.id !== id);
			if (svc) {
				pushEntry({
					kind: 'deleted',
					serviceName: svc.name,
					serviceUrl: svc.url,
					timestamp: new Date()
				});
			}
		} catch {
			// silent
		}
	}

	function toggleKiosk() {
		isKiosk = !isKiosk;
		requestAnimationFrame(() => {
			if (isKiosk) {
				document.documentElement.classList.add('kiosk-mode');
				requestWakeLock();
			} else {
				document.documentElement.classList.remove('kiosk-mode');
				releaseWakeLock();
				kioskFloating = false;
			}
		});
	}

	async function requestWakeLock() {
		try {
			if ('wakeLock' in navigator) {
				wakeLock = await navigator.wakeLock.request('screen');
				wakeLock.addEventListener('release', () => { wakeLock = null; });
			}
		} catch { /* wake lock not available */ }
	}

	function releaseWakeLock() {
		if (wakeLock) {
			wakeLock.release();
			wakeLock = null;
		}
	}

	function handleKioskMouseMove() {
		if (!isKiosk) return;
		kioskFloating = true;
		clearTimeout(kioskTimer);
		kioskTimer = setTimeout(() => { kioskFloating = false; }, 3000);
	}

	onMount(() => {
		const unsub = subscribeHeartbeats((hb) => {
			let wasUp: boolean | undefined;
			let changed = false;
			services = services.map((s) => {
				if (s.id !== hb.service_id) return s;
				if (s.last_heartbeat) {
					wasUp = s.last_heartbeat.is_up;
				}
				changed = true;
				return {
					...s,
					last_heartbeat: hb,
					heartbeats: [...s.heartbeats, hb].slice(-30)
				};
			});
			if (changed) pulseId += 1;

			const svc = services.find((s) => s.id === hb.service_id);
			if (!svc) return;

			const kind = wasUp !== undefined && wasUp !== hb.is_up ? 'transition' : 'check';
			pushEntry({
				kind,
				serviceName: svc.name,
				serviceUrl: svc.url,
				timestamp: new Date(),
				hb,
				wasUp
			});
		});
		return unsub;
	});
</script>

<svelte:head>
	<title>YAUM — Yet Another Uptime Monitor</title>
</svelte:head>

<div class="mb-8 flex items-start justify-between" class:kiosk-hidden={isKiosk}>
	<div>
		<h1 class="text-2xl font-semibold tracking-tight text-white">Dashboard</h1>
		<p class="mt-1 text-sm text-[var(--text-muted)]">Status dos serviços monitorados</p>
	</div>
	<button
		onclick={toggleKiosk}
		class="kiosk-hidden shrink-0 rounded-xl border border-[var(--border-color)] bg-[var(--bg-card)] px-3.5 py-2 text-xs font-medium text-[var(--text-muted)] transition-all hover:border-[var(--green)]/30 hover:text-[var(--green)]"
		title="Modo TV — tela cheia para monitores de parede"
	>
		<svg class="-ml-0.5 mr-1.5 inline h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5">
			<path stroke-linecap="round" stroke-linejoin="round" d="M9 17.25v1.007a3 3 0 01-.879 2.122L7.5 21h9l-.621-.621A3 3 0 0115 18.257V17.25m6-12V15a2.25 2.25 0 01-2.25 2.25H5.25A2.25 2.25 0 013 15V5.25A2.25 2.25 0 015.25 3h13.5A2.25 2.25 0 0121 5.25z" />
		</svg>
		Modo TV
	</button>
</div>

<!-- Floating exit button (kiosk only) -->
{#if isKiosk}
	<button
		onclick={toggleKiosk}
		class="fixed bottom-6 right-6 z-50 rounded-xl border border-white/10 bg-black/60 px-4 py-2.5 text-xs font-medium text-white/70 backdrop-blur-sm transition-all duration-300 hover:bg-black/80 hover:text-white"
		class:opacity-0={!kioskFloating}
		class:opacity-100={kioskFloating}
		class:pointer-events-none={!kioskFloating}
	>
		Sair do Modo TV
	</button>
{/if}

<!-- eslint-disable-next-line svelte/no-reactive-reassign -->
<div onmousemove={handleKioskMouseMove} role="region" class:kiosk-active={isKiosk} class:pulse={pulseId > 0} data-pulse={pulseId}>
{#if error}
	<div class="rounded-2xl border border-[var(--red)]/20 bg-[var(--red)]/5 p-8 text-center">
		<svg class="mx-auto mb-3 h-8 w-8 text-[var(--red)]/60" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5">
			<path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m9-.75a9 9 0 11-18 0 9 9 0 0118 0zm-9 3.75h.008v.008H12v-.008z" />
		</svg>
		<p class="text-sm text-[var(--red)]">{error}</p>
		<button
			onclick={() => location.reload()}
			class="mt-4 text-xs font-medium text-[var(--text-muted)] underline underline-offset-2 transition-colors hover:text-white"
		>
			Tentar novamente
		</button>
	</div>
{:else if services.length === 0}
	<div class="rounded-2xl border border-dashed border-[var(--border-color)] p-16 text-center">
		<div class="mx-auto mb-4 flex h-12 w-12 items-center justify-center rounded-xl bg-[var(--bg-card)]">
			<svg class="h-6 w-6 text-[var(--text-muted)]" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5">
				<path stroke-linecap="round" stroke-linejoin="round" d="M3.75 13.5l10.5-11.25L12 10.5h8.25L9.75 21.75 12 13.5H3.75z" />
			</svg>
		</div>
		<p class="text-sm font-medium text-[var(--text-secondary)]">Nenhum serviço sendo monitorado</p>
		<p class="mt-1 text-xs text-[var(--text-muted)]">Adicione o primeiro serviço para começar</p>
		<button
			onclick={() => (showModal = true)}
			class="mt-6 rounded-xl border border-[var(--green)]/30 bg-[var(--green)]/5 px-5 py-2 text-sm font-medium text-[var(--green)] transition-all hover:bg-[var(--green)]/10"
		>
			+ Adicionar Serviço
		</button>
	</div>
{:else}
	{#each [...new Set(services.map((s) => s.group_name || 'Geral'))].sort() as group}
		<div class="mb-8">
			<h2 class="mb-4 text-xs font-semibold uppercase tracking-wider text-[var(--text-secondary)]">{group}</h2>
			<div class="grid gap-4 sm:grid-cols-2 xl:grid-cols-3">
				{#each services.filter((s) => (s.group_name || 'Geral') === group) as svc (svc.id)}
					<ServiceCard service={svc} heartbeats={svc.heartbeats} ondeleted={handleDeleted} />
				{/each}
			</div>
		</div>
	{/each}

	<div class="mt-8">
		<ActivityLog entries={logEntries} />
	</div>
{/if}
</div>

<AddServiceModal
	show={showModal}
	onclose={() => (showModal = false)}
	oncreated={handleCreated}
/>
