<script lang="ts">
	import { get } from 'svelte/store';
	import type { ProxyRoute, ProxyRouteSource } from '$lib/types';
	import { proxyRoutesCache } from '$lib/stores/caches';
	import { toasts } from '$lib/stores/toast';
	import { t } from '$lib/i18n';
	import Skeleton from '$lib/components/Skeleton.svelte';
	import EmptyState from '$lib/components/EmptyState.svelte';
	import StatusBadge from '$lib/components/StatusBadge.svelte';
	import ForgeHero from '$lib/components/ForgeHero.svelte';

	type SourceFilter = 'all' | ProxyRouteSource;

	// Cache-backed (stale-while-revalidate) so revisiting this tab renders the
	// routes immediately instead of flashing the cold skeleton. See caches.ts.
	const routes = $derived<ProxyRoute[]>($proxyRoutesCache.value);
	const loading = $derived($proxyRoutesCache.loading);
	let search = $state('');
	let sourceFilter = $state<SourceFilter>('all');

	const counts = $derived({
		all: routes.length,
		instance: routes.filter((r) => r.source === 'instance').length,
		static_site: routes.filter((r) => r.source === 'static_site').length,
	});

	const filtered = $derived.by(() => {
		const q = search.trim().toLowerCase();
		return routes.filter((r) => {
			if (sourceFilter !== 'all' && r.source !== sourceFilter) return false;
			if (!q) return true;
			return (
				r.domain?.toLowerCase().includes(q) ||
				r.project_name.toLowerCase().includes(q) ||
				r.stage_name.toLowerCase().includes(q) ||
				r.image_tag.toLowerCase().includes(q)
			);
		});
	});

	function sourceLabel(route: ProxyRoute): string {
		if (route.source === 'static_site') {
			return route.stage_name === 'deno' ? $t('proxies.sourceDeno') : $t('proxies.sourceStatic');
		}
		return $t('proxies.sourceContainer');
	}

	function sourceBadgeClass(source: ProxyRouteSource): string {
		return source === 'static_site'
			? 'bg-[var(--color-accent-50)] text-[var(--color-accent-700)] dark:bg-[var(--color-accent-900)] dark:text-[var(--color-accent-200)]'
			: 'bg-[var(--color-brand-50)] text-[var(--color-brand-700)] dark:bg-[var(--color-brand-900)] dark:text-[var(--color-brand-200)]';
	}

	// Legacy /projects/{id} and /sites/{id} routes were retired with the
	// hard cutover. Proxy rows now point at the workload-first containers
	// page filtered by name; the app deep-link is not available because
	// proxy_route rows don't carry an app_id today.
	function targetHref(route: ProxyRoute): string {
		const q = encodeURIComponent(route.project_name ?? '');
		return q ? `/containers?q=${q}` : '/containers';
	}

	// `project_id` on a ProxyRoute is actually the workload ID
	// (back-compat naming — see internal/store/models.go:110-113). Anchor
	// at the bindings section on /apps/[id] so the operator lands directly
	// on the trigger list for this workload.
	function triggersHref(route: ProxyRoute): string {
		return route.project_id ? `/apps/${route.project_id}#bindings` : '/triggers';
	}

	async function loadRoutes() {
		await proxyRoutesCache.refresh();
		// Cache stores the error rather than throwing; surface it as a toast to
		// preserve the page's prior failure UX.
		const { error } = get(proxyRoutesCache);
		if (error) toasts.error(error || $t('proxies.loadFailed'));
	}

	$effect(() => {
		loadRoutes();
	});
</script>

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

<div class="space-y-6">
	<ForgeHero
		eyebrowSuffix={$t('nav.proxies').toUpperCase()}
		title={$t('proxies.title')}
		lede={$t('proxies.description')}
		size="lg"
	/>

	{#if loading}
		<div class="space-y-3">
			{#each Array(3) as _}
				<Skeleton height="4rem" />
			{/each}
		</div>
	{:else if routes.length === 0}
		<EmptyState title={$t('proxies.noRoutes')} description={$t('proxies.noRoutesDesc')} icon="instances" />
	{:else}
		<!-- Filters -->
		<div class="flex flex-wrap items-center gap-3">
			<input
				type="text"
				bind:value={search}
				placeholder={$t('proxies.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 text-sm" role="tablist" aria-label={$t('proxies.source')}>
				{#each [
					{ value: 'all' as const, label: $t('proxies.filterAll'), count: counts.all },
					{ value: 'instance' as const, label: $t('proxies.filterContainers'), count: counts.instance },
					{ value: 'static_site' as const, label: $t('proxies.filterSites'), count: counts.static_site },
				] as opt}
					<button
						type="button"
						role="tab"
						aria-selected={sourceFilter === opt.value}
						onclick={() => (sourceFilter = opt.value)}
						class="rounded-md px-3 py-1.5 transition-colors {sourceFilter === opt.value
							? 'bg-[var(--color-brand-500)] text-white shadow-[var(--shadow-xs)]'
							: 'text-[var(--text-secondary)] hover:text-[var(--text-primary)]'}"
					>
						{opt.label}
						<span class="ml-1 text-xs opacity-75">({opt.count})</span>
					</button>
				{/each}
			</div>
		</div>

		<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('proxies.domain')}</th>
						<th class="px-4 py-3 text-left text-xs font-medium text-[var(--text-tertiary)] uppercase">{$t('proxies.source')}</th>
						<th class="px-4 py-3 text-left text-xs font-medium text-[var(--text-tertiary)] uppercase">{$t('proxies.project')}</th>
						<th class="px-4 py-3 text-left text-xs font-medium text-[var(--text-tertiary)] uppercase">{$t('proxies.stage')}</th>
						<th class="px-4 py-3 text-left text-xs font-medium text-[var(--text-tertiary)] uppercase">{$t('proxies.tag')}</th>
						<th class="px-4 py-3 text-left text-xs font-medium text-[var(--text-tertiary)] uppercase">{$t('proxies.port')}</th>
						<th class="px-4 py-3 text-left text-xs font-medium text-[var(--text-tertiary)] uppercase">{$t('proxies.status')}</th>
						<th class="px-4 py-3 text-right text-xs font-medium text-[var(--text-tertiary)] uppercase">{$t('proxies.actions')}</th>
					</tr>
				</thead>
				<tbody class="divide-y divide-[var(--border-secondary)]">
					{#each filtered as route (route.source + ':' + route.instance_id)}
						<tr class="hover:bg-[var(--surface-card-hover)] transition-colors">
							<td class="px-4 py-3">
								{#if route.domain}
									<a href="https://{route.domain}" target="_blank" rel="noopener noreferrer" class="text-sm font-medium text-[var(--text-link)] hover:text-[var(--text-link-hover)] underline transition-colors">
										{route.domain}
									</a>
								{:else}
									<span class="text-sm text-[var(--text-tertiary)]">{route.subdomain || '—'}</span>
								{/if}
							</td>
							<td class="px-4 py-3">
								<span class="inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium {sourceBadgeClass(route.source)}">
									{sourceLabel(route)}
								</span>
							</td>
							<td class="px-4 py-3">
								<a href={targetHref(route)} class="text-sm font-medium text-[var(--text-primary)] hover:text-[var(--text-link)] transition-colors">
									{route.project_name}
								</a>
							</td>
							<td class="px-4 py-3 text-sm text-[var(--text-secondary)]">{route.stage_name || '—'}</td>
							<td class="px-4 py-3">
								{#if route.image_tag}
									<span class="rounded-full bg-[var(--surface-card-hover)] px-2 py-0.5 text-xs font-mono text-[var(--text-secondary)]">{route.image_tag}</span>
								{:else}
									<span class="text-sm text-[var(--text-tertiary)]">—</span>
								{/if}
							</td>
							<td class="px-4 py-3 text-sm font-mono text-[var(--text-secondary)]">{route.port > 0 ? route.port : '—'}</td>
							<td class="px-4 py-3">
								<StatusBadge status={route.status} />
							</td>
							<td class="px-4 py-3 text-right">
								{#if route.project_id}
									<a
										href={triggersHref(route)}
										title={$t('proxies.viewTriggersTitle')}
										class="inline-flex items-center rounded-md border border-[var(--border-primary)] bg-[var(--surface-card)] px-2.5 py-1 text-xs font-medium text-[var(--text-secondary)] transition-colors hover:border-[var(--color-brand-500)] hover:text-[var(--text-primary)]"
									>
										{$t('proxies.viewTriggers')}
									</a>
								{:else}
									<span class="text-xs text-[var(--text-tertiary)]">—</span>
								{/if}
							</td>
						</tr>
					{/each}
				</tbody>
			</table>
		</div>

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

		<p class="text-xs text-[var(--text-tertiary)]">
			{filtered.length} {filtered.length === 1 ? $t('proxies.route') : $t('proxies.routes')}
		</p>
	{/if}
</div>
