<script lang="ts">
	import * as api from '$lib/api';
	import { staleContainersCache } from '$lib/stores/caches';
	import ConfirmDialog from '$lib/components/ConfirmDialog.svelte';
	import EmptyState from '$lib/components/EmptyState.svelte';
	import SkeletonCard from '$lib/components/SkeletonCard.svelte';
	import ForgeHero from '$lib/components/ForgeHero.svelte';
	import { IconTrash, IconLoader } from '$lib/components/icons';
	import { toasts } from '$lib/stores/toast';
	import { t } from '$lib/i18n';
	import { fmt } from '$lib/format/datetime';

	// Cache-backed (stale-while-revalidate) so revisiting renders instantly
	// instead of flashing the cold skeleton; the cache aborts a prior in-flight
	// fetch on the next refresh (replacing the old manual loadController guard).
	const containers = $derived($staleContainersCache.value);
	const loading = $derived($staleContainersCache.loading);
	const error = $derived($staleContainersCache.error);

	let confirmSingleId = $state('');
	let confirmBulk = $state(false);
	let cleaningIds = $state<Set<string>>(new Set());
	let bulkCleaning = $state(false);

	const loadStale = () => staleContainersCache.refresh();

	function requestCleanup(id: string) {
		confirmSingleId = id;
	}

	async function handleConfirmCleanup() {
		const id = confirmSingleId;
		confirmSingleId = '';
		cleaningIds = new Set([...cleaningIds, id]);
		try {
			await api.cleanupStaleContainer(id);
			await staleContainersCache.refresh();
			toasts.success($t('stale.cleanedUp'));
		} catch (e) {
			toasts.error(e instanceof Error ? e.message : $t('stale.cleanupFailed'));
		} finally {
			const next = new Set(cleaningIds);
			next.delete(id);
			cleaningIds = next;
		}
	}

	async function handleConfirmBulkCleanup() {
		confirmBulk = false;
		bulkCleaning = true;
		try {
			const result = await api.bulkCleanupStaleContainers();
			await staleContainersCache.refresh();
			toasts.success($t('stale.bulkCleanedUp', { count: String(result.deleted) }));
		} catch (e) {
			toasts.error(e instanceof Error ? e.message : $t('stale.cleanupFailed'));
		} finally {
			bulkCleaning = false;
		}
	}

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

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

<div class="space-y-6">
	{#snippet heroToolbar()}
		{#if containers.length > 0}
			<button
				type="button"
				disabled={bulkCleaning}
				onclick={() => { confirmBulk = true; }}
				class="forge-btn-ghost forge-btn-danger"
			>
				{#if bulkCleaning}<IconLoader size={14} />{/if}
				<IconTrash size={14} />
				<span>{$t('stale.cleanupAll')}</span>
			</button>
		{/if}
	{/snippet}
	<ForgeHero
		backHref="/"
		eyebrowSuffix={$t('stale.eyebrowSuffix')}
		title={$t('stale.title')}
		size="lg"
		toolbar={heroToolbar}
	/>

	<!-- Content -->
	{#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={loadStale}
			>
				{$t('common.retry')}
			</button>
		</div>
	{:else if containers.length === 0}
		<EmptyState
			title={$t('stale.noStale')}
			description={$t('stale.noStaleDesc')}
			icon="instances"
		/>
	{:else}
		<div class="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">
			{#each containers as entry (entry.container.id)}
				{@const c = entry.container}
				{@const cleaning = cleaningIds.has(c.id)}
				<article class="stale-card">
					<header class="stale-card-head">
						<div class="stale-card-title">
							<span class="stale-workload">{entry.workload_name || c.workload_id || '—'}</span>
							{#if entry.role}
								<span class="stale-role">/ {entry.role}</span>
							{/if}
						</div>
						<span class="stale-pill" title={$t('stale.daysStale')}>{entry.days_stale}d</span>
					</header>
					<dl class="stale-meta">
						<div><dt>{$t('common.running')}</dt><dd>{c.state}</dd></div>
						<div><dt>image</dt><dd class="truncate">{c.image_ref}{c.image_tag ? ':' + c.image_tag : ''}</dd></div>
						{#if c.last_seen_at}
							<div><dt>{$t('stale.lastAlive')}</dt><dd>{$fmt.dateTime(c.last_seen_at)}</dd></div>
						{/if}
					</dl>
					<footer class="stale-card-foot">
						<button
							type="button"
							class="forge-btn-ghost forge-btn-danger"
							disabled={cleaning}
							onclick={() => requestCleanup(c.id)}
						>
							{#if cleaning}<IconLoader size={14} />{/if}
							<IconTrash size={14} />
							<span>{$t('stale.cleanup')}</span>
						</button>
					</footer>
				</article>
			{/each}
		</div>
	{/if}
</div>

<style>
	.stale-card {
		display: flex;
		flex-direction: column;
		gap: 0.75rem;
		padding: 1rem;
		border: 1px solid var(--border-primary);
		border-radius: var(--radius-md, 0.75rem);
		background: var(--surface-card);
		box-shadow: var(--shadow-sm);
	}
	.stale-card-head {
		display: flex;
		align-items: flex-start;
		justify-content: space-between;
		gap: 0.5rem;
	}
	.stale-card-title {
		min-width: 0;
		display: flex;
		gap: 0.35rem;
		font-size: 0.9rem;
		font-weight: 600;
		color: var(--text-primary);
	}
	.stale-workload {
		max-width: 100%;
		overflow: hidden;
		text-overflow: ellipsis;
		white-space: nowrap;
	}
	.stale-role {
		color: var(--text-tertiary);
		font-weight: 400;
	}
	.stale-pill {
		flex-shrink: 0;
		padding: 0.15rem 0.55rem;
		border-radius: 999px;
		font-family: var(--forge-mono, 'JetBrains Mono', monospace);
		font-size: 0.7rem;
		font-weight: 700;
		letter-spacing: 0.04em;
		color: var(--color-danger-dark);
		background: var(--color-danger-light);
	}
	.stale-meta {
		display: grid;
		gap: 0.3rem;
		font-size: 0.75rem;
		color: var(--text-secondary);
		margin: 0;
	}
	.stale-meta > div {
		display: grid;
		grid-template-columns: 5.5rem 1fr;
		gap: 0.5rem;
	}
	.stale-meta dt {
		color: var(--text-tertiary);
		text-transform: uppercase;
		font-size: 0.62rem;
		letter-spacing: 0.06em;
	}
	.stale-meta dd {
		margin: 0;
		min-width: 0;
		overflow: hidden;
		text-overflow: ellipsis;
		white-space: nowrap;
		font-family: var(--forge-mono, 'JetBrains Mono', monospace);
	}
	.stale-card-foot {
		display: flex;
		justify-content: flex-end;
		padding-top: 0.25rem;
		border-top: 1px dashed var(--border-primary);
	}
</style>

<!-- Single cleanup confirm -->
<ConfirmDialog
	open={confirmSingleId !== ''}
	title={$t('stale.cleanup')}
	message={$t('stale.confirmCleanup')}
	confirmLabel={$t('stale.cleanup')}
	confirmVariant="danger"
	onconfirm={handleConfirmCleanup}
	oncancel={() => { confirmSingleId = ''; }}
/>

<!-- Bulk cleanup confirm -->
<ConfirmDialog
	open={confirmBulk}
	title={$t('stale.cleanupAll')}
	message={$t('stale.confirmBulkCleanup')}
	confirmLabel={$t('stale.cleanupAll')}
	confirmVariant="danger"
	onconfirm={handleConfirmBulkCleanup}
	oncancel={() => { confirmBulk = false; }}
/>
