<script lang="ts">
	import { goto } from '$app/navigation';
	import { page } from '$app/stores';
	import type { ContainerView, WorkloadKind } from '$lib/types';
	import { containersCache } from '$lib/stores/caches';
	import EmptyState from '$lib/components/EmptyState.svelte';
	import SkeletonCard from '$lib/components/SkeletonCard.svelte';
	import ForgeHero from '$lib/components/ForgeHero.svelte';
	import StatusBadge from '$lib/components/StatusBadge.svelte';
	import { IconRefresh } from '$lib/components/icons';
	import { t } from '$lib/i18n';
	import { fmt } from '$lib/format/datetime';

	// allContainers holds the unfiltered list — kind/state filters are applied
	// client-side so the tab counters reflect the whole population, not the
	// current narrowed view (otherwise picking "Project" would show All=0).
	//
	// Cache-backed (stale-while-revalidate): the list persists across
	// navigation, so revisiting this tab renders immediately instead of
	// flashing the cold skeleton. The cache's abort-on-refresh replaces the
	// previous manual `loadSeq` race guard.
	const allContainers = $derived($containersCache.value);
	const loading = $derived($containersCache.loading);
	const refreshing = $derived($containersCache.refreshing);
	const error = $derived($containersCache.error);

	// Filters seed from query string so the tab is shareable / refresh-safe.
	const initialKind = (() => {
		const k = $page.url.searchParams.get('kind') ?? '';
		if (k === 'project' || k === 'stack' || k === 'site') return k;
		return '';
	})();
	const initialState = $page.url.searchParams.get('state') ?? '';
	const initialQ = $page.url.searchParams.get('q') ?? '';

	let kindFilter = $state<'' | WorkloadKind>(initialKind);
	let stateFilter = $state(initialState);
	let searchTerm = $state(initialQ);

	// `initial` is retained for call-site compatibility; the cache distinguishes
	// the cold load (skeleton) from background refreshes on its own.
	const load = (_initial = false): Promise<void> => containersCache.refresh();

	$effect(() => {
		void load(true);
	});

	// Keep URL params in sync so reload + share-link Just Work.
	$effect(() => {
		const params = new URLSearchParams();
		if (kindFilter !== '') params.set('kind', kindFilter);
		if (stateFilter !== '') params.set('state', stateFilter);
		if (searchTerm !== '') params.set('q', searchTerm);
		const target = params.toString() ? `?${params.toString()}` : window.location.pathname;
		const current = window.location.search.replace(/^\?/, '');
		if (current !== params.toString()) {
			void goto(target, { replaceState: true, keepFocus: true, noScroll: true });
		}
	});

	const filteredByKindState = $derived.by(() => {
		return allContainers.filter((c) => {
			if (kindFilter !== '' && c.workload_kind !== kindFilter) return false;
			if (stateFilter !== '' && c.state !== stateFilter) return false;
			return true;
		});
	});

	const visible = $derived.by(() => {
		const term = searchTerm.trim().toLowerCase();
		if (term === '') return filteredByKindState;
		return filteredByKindState.filter((c) => {
			return (
				c.workload_name.toLowerCase().includes(term) ||
				c.role.toLowerCase().includes(term) ||
				c.image_ref.toLowerCase().includes(term) ||
				c.subdomain.toLowerCase().includes(term) ||
				c.container_id.startsWith(term)
			);
		});
	});

	const stateCounts = $derived.by(() => {
		const out: Record<string, number> = {};
		for (const c of allContainers) {
			out[c.state] = (out[c.state] ?? 0) + 1;
		}
		return out;
	});

	const kindCounts = $derived.by(() => {
		const out: Record<string, number> = { project: 0, stack: 0, site: 0 };
		for (const c of allContainers) {
			out[c.workload_kind] = (out[c.workload_kind] ?? 0) + 1;
		}
		return out;
	});

	function kindLabel(k: WorkloadKind): string {
		switch (k) {
			case 'project':
				return $t('common.project');
			case 'stack':
				return $t('common.stack');
			case 'site':
				return $t('common.site');
			default:
				return k;
		}
	}

	function detailHref(c: ContainerView): string | undefined {
		// Legacy project / stack / site detail pages were retired with the
		// hard cutover. The workload-first equivalent lives under /apps —
		// every workload now belongs to an app, so the row deep-links to
		// the app detail page when one is attached, otherwise stays flat.
		return c.app_id ? `/apps/${c.app_id}` : undefined;
	}

	function tabClass(active: boolean): string {
		return active
			? 'rounded-md px-3 py-1.5 text-sm bg-[var(--color-brand-500)] text-white shadow-[var(--shadow-xs)]'
			: 'rounded-md px-3 py-1.5 text-sm text-[var(--text-secondary)] hover:text-[var(--text-primary)]';
	}
</script>

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

<div class="space-y-6">
	{#snippet heroToolbar()}
		<button
			type="button"
			disabled={refreshing}
			onclick={() => void load(false)}
			class="forge-btn-ghost"
		>
			<IconRefresh size={14} />
			<span>{$t('common.refresh')}</span>
		</button>
	{/snippet}
	<ForgeHero
		backHref="/"
		eyebrowSuffix={$t('containers.eyebrowSuffix')}
		title={$t('nav.containers')}
		size="lg"
		toolbar={heroToolbar}
	/>

	{#if loading}
		<div class="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">
			{#each { length: 3 } as _, i (i)}
				<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>
		</div>
	{:else}
		<!-- Filter bar -->
		<div class="flex flex-wrap items-center gap-3">
			<input
				type="text"
				bind:value={searchTerm}
				placeholder={$t('containers.searchPlaceholder')}
				class="w-full max-w-md rounded-lg border border-[var(--border-input)] bg-[var(--surface-input)] px-3 py-2 text-sm text-[var(--text-primary)] placeholder:text-[var(--text-tertiary)] focus:border-[var(--color-brand-500)] focus:outline-none focus:ring-1 focus:ring-[var(--color-brand-500)]"
			/>

			<div class="inline-flex rounded-lg border border-[var(--border-primary)] bg-[var(--surface-card)] p-0.5" role="tablist" aria-label={$t('containers.kindFilterLabel')}>
				{#each [
					{ value: '' as const, label: $t('common.all'), count: allContainers.length },
					{ value: 'project' as const, label: kindLabel('project'), count: kindCounts.project ?? 0 },
					{ value: 'stack' as const, label: kindLabel('stack'), count: kindCounts.stack ?? 0 },
					{ value: 'site' as const, label: kindLabel('site'), count: kindCounts.site ?? 0 }
				] as opt (opt.value || 'all')}
					<button
						type="button"
						role="tab"
						aria-selected={kindFilter === opt.value}
						onclick={() => {
							kindFilter = opt.value;
						}}
						class={tabClass(kindFilter === opt.value)}
					>
						{opt.label}<span class="ml-1 text-xs opacity-75">({opt.count})</span>
					</button>
				{/each}
			</div>

			<div class="inline-flex rounded-lg border border-[var(--border-primary)] bg-[var(--surface-card)] p-0.5" role="tablist" aria-label={$t('containers.stateFilterLabel')}>
				{#each [
					{ value: '', label: $t('common.all') },
					{ value: 'running', label: $t('common.running') },
					{ value: 'stopped', label: $t('common.stopped') },
					{ value: 'missing', label: $t('common.missing') }
				] as opt (opt.value || 'all')}
					<button
						type="button"
						role="tab"
						aria-selected={stateFilter === opt.value}
						onclick={() => {
							stateFilter = opt.value;
						}}
						class={tabClass(stateFilter === opt.value)}
					>
						{opt.label}{#if opt.value !== '' && stateCounts[opt.value]}<span class="ml-1 text-xs opacity-75">({stateCounts[opt.value]})</span>{/if}
					</button>
				{/each}
			</div>
		</div>

		{#if allContainers.length === 0}
			<EmptyState
				title={$t('containers.emptyTitle')}
				description={$t('containers.emptyDesc')}
			/>
		{:else}
			<div class="overflow-x-auto rounded-xl border border-[var(--border-primary)] bg-[var(--surface-card)] shadow-[var(--shadow-sm)]">
				<table class="min-w-full divide-y divide-[var(--border-primary)]">
					<thead class="bg-[var(--surface-card-hover)]">
						<tr>
							<th class="px-4 py-3 text-left text-xs font-medium text-[var(--text-tertiary)] uppercase">{$t('containers.col.workload')}</th>
							<th class="px-4 py-3 text-left text-xs font-medium text-[var(--text-tertiary)] uppercase">{$t('containers.col.kind')}</th>
							<th class="px-4 py-3 text-left text-xs font-medium text-[var(--text-tertiary)] uppercase">{$t('containers.col.role')}</th>
							<th class="px-4 py-3 text-left text-xs font-medium text-[var(--text-tertiary)] uppercase">{$t('containers.col.image')}</th>
							<th class="px-4 py-3 text-left text-xs font-medium text-[var(--text-tertiary)] uppercase">{$t('containers.col.state')}</th>
							<th class="px-4 py-3 text-left text-xs font-medium text-[var(--text-tertiary)] uppercase">{$t('containers.col.subdomain')}</th>
							<th class="px-4 py-3 text-left text-xs font-medium text-[var(--text-tertiary)] uppercase">{$t('containers.col.lastSeen')}</th>
						</tr>
					</thead>
					<tbody class="divide-y divide-[var(--border-secondary)]">
						{#each visible as c (c.id)}
							{@const href = detailHref(c)}
							<tr class="hover:bg-[var(--surface-card-hover)] transition-colors">
								<td class="px-4 py-3">
									{#if href}
										<a
											{href}
											class="text-sm font-medium text-[var(--text-primary)] hover:text-[var(--text-link)] transition-colors"
										>{c.workload_name || c.workload_id}</a>
									{:else}
										<span class="text-sm font-medium text-[var(--text-tertiary)]">{c.workload_name || c.workload_id}</span>
									{/if}
									{#if c.app_name}
										<span class="ml-2 rounded bg-[var(--surface-card-hover)] px-1.5 py-0.5 text-xs text-[var(--text-tertiary)]">
											{c.app_name}
										</span>
									{/if}
								</td>
								<td class="px-4 py-3 text-sm text-[var(--text-secondary)]">
									<span class="inline-flex items-center rounded-full bg-[var(--surface-card-hover)] px-2 py-0.5 text-xs font-medium">
										{kindLabel(c.workload_kind)}
									</span>
								</td>
								<td class="px-4 py-3 text-sm text-[var(--text-secondary)]">
									{c.role || '—'}
								</td>
								<td class="px-4 py-3 font-mono text-xs text-[var(--text-secondary)] truncate" style="max-width: 320px;">
									{c.image_ref || '—'}
								</td>
								<td class="px-4 py-3">
									<StatusBadge status={c.state} />
								</td>
								<td class="px-4 py-3 font-mono text-xs text-[var(--text-secondary)]">
									{c.subdomain || '—'}
								</td>
								<td class="px-4 py-3 text-xs text-[var(--text-tertiary)]">
									{c.last_seen_at ? $fmt.relative(c.last_seen_at) : '—'}
								</td>
							</tr>
						{/each}
					</tbody>
				</table>
			</div>

			{#if visible.length === 0}
				<p class="text-center text-sm text-[var(--text-tertiary)]">{$t('containers.noMatch')}</p>
			{/if}

			<p class="text-xs text-[var(--text-tertiary)]">
				{$t('containers.showingN', { visible: String(visible.length), total: String(allContainers.length) })}
			</p>
		{/if}
	{/if}
</div>
