<script lang="ts">
	// Workload-first dashboard. Replaces the legacy project / site
	// summaries with a single workload count grouped by source_kind and
	// a running-container tally pulled from /api/containers.
	//
	// We no longer fan out N+1 fetches per project to gather instance
	// status — the global containers index already carries the workload
	// reference and state.
	import type { ContainerView, StaleContainer, Workload } from '$lib/types';
	import * as api from '$lib/api';
	import SkeletonCard from '$lib/components/SkeletonCard.svelte';
	import EmptyState from '$lib/components/EmptyState.svelte';
	import SystemHealthCard from '$lib/components/SystemHealthCard.svelte';
	import SystemDaemonsCard from '$lib/components/SystemDaemonsCard.svelte';
	import SystemResourcesCard from '$lib/components/SystemResourcesCard.svelte';
	import CollapsibleSection from '$lib/components/CollapsibleSection.svelte';
	import ForgeHero from '$lib/components/ForgeHero.svelte';
	import StatusBadge from '$lib/components/StatusBadge.svelte';
	import { IconBox, IconAlert } from '$lib/components/icons';
	import { t } from '$lib/i18n';
	import { fmt } from '$lib/format/datetime';

	let workloads = $state<Workload[]>([]);
	let containers = $state<ContainerView[]>([]);
	let staleContainers = $state<StaleContainer[]>([]);
	let unusedImagesMB = $state(0);
	let unusedImagesCount = $state(0);
	let unusedImagesExceeded = $state(false);
	let loading = $state(true);
	let error = $state('');
	let loadController: AbortController | null = null;

	async function loadDashboard() {
		loadController?.abort();
		const controller = new AbortController();
		loadController = controller;
		const signal = controller.signal;

		loading = true;
		error = '';
		try {
			// Parallelize the cheap top-level reads. Each falls back to an
			// empty list so a single slow daemon (e.g. Docker stats) does
			// not blank the entire dashboard.
			const [wls, ctrs, stale] = await Promise.all([
				api.listWorkloads(undefined, signal),
				api.listContainers({}, signal).catch(() => [] as ContainerView[]),
				api.fetchStaleContainers(signal).catch(() => [] as StaleContainer[])
			]);
			workloads = wls;
			containers = ctrs;
			staleContainers = stale;

			try {
				const imgStats = await api.getUnusedImageStats(signal);
				unusedImagesMB = imgStats.total_size_mb;
				unusedImagesCount = imgStats.count;
				unusedImagesExceeded = imgStats.exceeded;
			} catch { /* non-critical */ }
		} catch (e) {
			if (e instanceof DOMException && e.name === 'AbortError') return;
			error = e instanceof Error ? e.message : $t('dashboard.loadFailed');
		} finally {
			loading = false;
		}
	}

	$effect(() => {
		loadDashboard();
		return () => { loadController?.abort(); };
	});

	// Plugin-native workloads only. Legacy pre-cutover rows (kind project/
	// stack/site) carry an empty source_kind and have no UI home post-cutover,
	// so they must not inflate the headline count or the recent strip — this
	// matches the /apps list, which shows the same set.
	const pluginWorkloads = $derived(workloads.filter((w) => w.source_kind !== ''));
	const totalWorkloads = $derived(pluginWorkloads.length);
	const totalRunning = $derived(containers.filter((c) => c.state === 'running').length);
	const totalFailed = $derived(containers.filter((c) => c.state === 'failed').length);
	const totalStale = $derived(staleContainers.length);

	// Latest 6 workloads by updated_at desc — enough for an at-a-glance
	// recent-activity strip without paging the entire list.
	const recentWorkloads = $derived(
		[...pluginWorkloads]
			.sort((a, b) => (b.updated_at ?? '').localeCompare(a.updated_at ?? ''))
			.slice(0, 6)
	);

	function containerStateFor(workloadID: string): string {
		// Pick the most informative state across this workload's
		// containers: failed > running > stopped > anything else.
		const states = containers.filter((c) => c.workload_id === workloadID).map((c) => c.state);
		if (states.length === 0) return 'idle';
		if (states.includes('failed')) return 'failed';
		if (states.includes('running')) return 'running';
		if (states.includes('stopped')) return 'stopped';
		return states[0];
	}

	function containerCountFor(workloadID: string): number {
		return containers.filter((c) => c.workload_id === workloadID).length;
	}
</script>

<svelte:head>
	<title>{$t('dashboard.title')} - {$t('app.name')}</title>
</svelte:head>

<div class="space-y-6 dashboard">
	<!-- Hero -->
	{#snippet heroToolbar()}
		<a href="/apps/new" class="forge-btn">
			<IconBox size={14} />
			<span>{$t('dashboard.newApp')}</span>
		</a>
	{/snippet}
	<ForgeHero
		eyebrow="THE FORGE"
		eyebrowSuffix={$t('nav.dashboard').toUpperCase()}
		title={$t('dashboard.title')}
		accent="."
		size="lg"
		toolbar={heroToolbar}
	/>

	<!-- Stats grid -->
	<div class="forge-stat-grid">
		<a href="/apps" class="forge-stat stat-link">
			<span class="forge-stat-label">{$t('dashboard.totalWorkloads')}</span>
			<span class="forge-stat-value">{String(totalWorkloads).padStart(2, '0')}</span>
			<span class="forge-stat-sub">{$t('dashboard.statSubWorkloads')}</span>
		</a>
		<a href="/containers" class="forge-stat stat-link">
			<span class="forge-stat-label">{$t('dashboard.runningContainers')}</span>
			<span class="forge-stat-value accent">{String(totalRunning).padStart(2, '0')}</span>
			<span class="forge-stat-sub">{$t('dashboard.statSubRunning')}</span>
		</a>
		<a href="/containers?state=failed" class="forge-stat stat-link">
			<span class="forge-stat-label">{$t('dashboard.failedContainers')}</span>
			<span class="forge-stat-value" class:fail={totalFailed > 0}>{String(totalFailed).padStart(2, '0')}</span>
			<span class="forge-stat-sub">{$t('dashboard.statSubNeedAttention')}</span>
		</a>
		<a href="/containers/stale" class="forge-stat stat-link">
			<span class="forge-stat-label">{$t('dashboard.staleContainers')}</span>
			<span class="forge-stat-value" class:warn={totalStale > 0}>{String(totalStale).padStart(2, '0')}</span>
			<span class="forge-stat-sub">{$t('dashboard.statSubStale')}</span>
		</a>
	</div>

	<!-- Unused images warning -->
	{#if unusedImagesExceeded}
		<a href="/settings" class="flex items-center gap-3 rounded-xl border border-amber-300 bg-amber-50 dark:border-amber-700 dark:bg-amber-950/30 p-4 transition-colors hover:bg-amber-100 dark:hover:bg-amber-950/50">
			<div class="flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-amber-100 dark:bg-amber-900/50 text-amber-600">
				<IconAlert size={20} />
			</div>
			<div class="flex-1">
				<p class="text-sm font-medium text-amber-800 dark:text-amber-300">{$t('dashboard.unusedImagesWarning')}</p>
				<p class="text-xs text-amber-700 dark:text-amber-400">{unusedImagesCount} {$t('dashboard.unusedImages')} &middot; {unusedImagesMB >= 1024 ? (unusedImagesMB / 1024).toFixed(1) + ' GB' : unusedImagesMB + ' MB'}</p>
			</div>
			<span class="text-xs font-medium text-amber-600 dark:text-amber-400">{$t('settings.pruneImages')} &rarr;</span>
		</a>
	{/if}

	<!-- System health summary -->
	<CollapsibleSection id="system-health" title={$t('dashboard.systemHealth')}>
		<SystemHealthCard />
	</CollapsibleSection>

	<!-- Detailed daemon panel: Docker engine + NPM/Traefik proxy -->
	<CollapsibleSection id="system-daemons" title={$t('dashboard.daemons')} defaultOpen={false}>
		<SystemDaemonsCard />
	</CollapsibleSection>

	<!-- Host CPU/memory/disk + top consumers -->
	<CollapsibleSection
		id="system-resources"
		title={$t('dashboard.systemResources')}
		subtitle={$t('dashboard.systemResourcesSubtitle')}
	>
		<SystemResourcesCard />
	</CollapsibleSection>

	<!-- Recent workloads strip -->
	<CollapsibleSection
		id="dashboard-workloads"
		title={$t('dashboard.recentWorkloads')}
		badge={!loading && workloads.length > 0 ? String(workloads.length) : ''}
	>
		{#if loading}
			<div class="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">
				{#each Array(3) as _}
					<SkeletonCard />
				{/each}
			</div>
		{:else if error}
			<div class="rounded-xl border border-[var(--color-danger-light)] bg-[var(--color-danger-light)] p-4">
				<p class="text-sm text-[var(--color-danger)]">{error}</p>
				<button
					type="button"
					class="mt-2 text-sm font-medium text-[var(--color-danger)] underline hover:no-underline"
					onclick={loadDashboard}
				>
					{$t('dashboard.retry')}
				</button>
			</div>
		{:else if workloads.length === 0}
			<EmptyState
				title={$t('dashboard.noWorkloads')}
				description={$t('dashboard.noWorkloadsDesc')}
				actionLabel={$t('dashboard.newApp')}
				actionHref="/apps/new"
				icon="projects"
			/>
		{:else}
			<div class="grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-3">
				{#each recentWorkloads as wl (wl.id)}
					{@const state = containerStateFor(wl.id)}
					{@const count = containerCountFor(wl.id)}
					<a
						href={wl.app_id ? `/apps/${wl.app_id}` : '/apps'}
						class="flex flex-col gap-2 rounded-xl border border-[var(--border-primary)] bg-[var(--surface-card)] p-4 shadow-[var(--shadow-sm)] transition-colors hover:bg-[var(--surface-card-hover)]"
					>
						<div class="flex items-center justify-between gap-2">
							<span class="truncate font-medium text-[var(--text-primary)]">{wl.name}</span>
							<StatusBadge status={state} size="sm" />
						</div>
						<div class="flex items-center gap-3 text-xs text-[var(--text-secondary)]">
							<span class="truncate">{wl.source_kind || wl.kind}</span>
							<span class="opacity-60">·</span>
							<span>{count} {count === 1 ? $t('common.instance') : $t('common.instances')}</span>
						</div>
						{#if wl.updated_at}
							<p class="text-xs text-[var(--text-tertiary)]">{$fmt.dateTime(wl.updated_at)}</p>
						{/if}
					</a>
				{/each}
			</div>
		{/if}
	</CollapsibleSection>
</div>

<style>
	.dashboard { position: relative; }

	.stat-link {
		text-decoration: none;
		transition: background 150ms ease;
	}
	.stat-link:hover { background: var(--surface-card-hover); }
</style>
