<script lang="ts">
	/**
	 * DeployHistoryPanel
	 *
	 * Per-workload structured deploy ledger (success + failure) with one-click
	 * rollback. This is the actionable sibling of the free-text activity
	 * timeline: each row carries a version-pinned `reference` the rollback
	 * action replays. The "Roll back" affordance only appears on rows the
	 * server marked `rollbackable` (a successful deploy of a reference-pinned
	 * source kind — image today); the server re-checks on POST, so the button
	 * is a convenience, not the authority.
	 */
	import * as api from '$lib/api';
	import { t } from '$lib/i18n';
	import { toasts } from '$lib/stores/toast';
	import { fmt } from '$lib/format/datetime';
	import StatusBadge from './StatusBadge.svelte';
	import ConfirmDialog from './ConfirmDialog.svelte';
	import { IconRestart, IconRefresh } from './icons';

	interface Props {
		workloadId: string;
	}
	let { workloadId }: Props = $props();

	let deploys = $state<api.DeployHistoryEntry[]>([]);
	let loading = $state(true);
	let error = $state('');
	let rollingBack = $state(false);
	let confirmEntry = $state<api.DeployHistoryEntry | null>(null);

	async function load(): Promise<void> {
		loading = true;
		error = '';
		try {
			deploys = await api.fetchWorkloadDeploys(workloadId, { limit: 50 });
		} catch (e) {
			error = e instanceof Error ? e.message : String(e);
		} finally {
			loading = false;
		}
	}

	// Reload whenever workloadId changes — the parent reuses this instance
	// across /apps/A → /apps/B navigation.
	$effect(() => {
		const _ = workloadId;
		load();
	});

	async function doRollback(entry: api.DeployHistoryEntry): Promise<void> {
		if (rollingBack) return;
		rollingBack = true;
		try {
			await api.rollbackWorkload(workloadId, entry.id);
			toasts.success($t('apps.detail.deployHistory.rolledBack', { ref: shortRef(entry.reference) }));
			await load();
		} catch (e) {
			toasts.error(e instanceof Error ? e.message : $t('apps.detail.deployHistory.rollbackFailed'));
		} finally {
			rollingBack = false;
			confirmEntry = null;
		}
	}

	// Tags render in full; long commit SHAs are clipped to the first 10 chars.
	function shortRef(ref: string): string {
		if (!ref) return '—';
		return /^[0-9a-f]{16,}$/i.test(ref) ? ref.slice(0, 10) : ref;
	}
</script>

<section class="panel dh-panel" aria-labelledby="dh-heading">
	<span class="reg reg-tl" aria-hidden="true"></span>
	<span class="reg reg-tr" aria-hidden="true"></span>
	<span class="reg reg-bl" aria-hidden="true"></span>
	<span class="reg reg-br" aria-hidden="true"></span>

	<header class="panel-head">
		<h2 class="panel-title" id="dh-heading">
			{$t('apps.detail.deployHistory.title')}<span class="title-accent">.</span>
		</h2>
		<span class="panel-sub">{$t('apps.detail.deployHistory.sub')}</span>
		<button
			class="forge-btn-ghost dh-refresh"
			onclick={load}
			disabled={loading}
			aria-label={$t('common.refresh')}
		>
			<IconRefresh size={13} />
		</button>
	</header>

	{#if error}
		<div class="alert inline-alert" role="alert">
			<span class="alert-tag">ERR</span><span>{error}</span>
		</div>
	{/if}

	{#if loading}
		<p class="hint">{$t('apps.detail.deployHistory.loading')}</p>
	{:else if deploys.length === 0}
		<p class="hint">{$t('apps.detail.deployHistory.empty')}</p>
	{:else}
		<table class="forge-table dh-table">
			<thead>
				<tr>
					<th>{$t('apps.detail.deployHistory.colWhen')}</th>
					<th>{$t('apps.detail.deployHistory.colReason')}</th>
					<th>{$t('apps.detail.deployHistory.colReference')}</th>
					<th>{$t('apps.detail.deployHistory.colOutcome')}</th>
					<th>{$t('apps.detail.deployHistory.colBy')}</th>
					<th></th>
				</tr>
			</thead>
			<tbody>
				{#each deploys as d (d.id)}
					<tr>
						<td class="mono-time" title={$fmt.dateTime(d.finished_at)}>{$fmt.relative(d.finished_at)}</td>
						<td><span class="reason-tag">{d.reason || '—'}</span></td>
						<td class="mono" title={d.reference}>{shortRef(d.reference)}</td>
						<td><StatusBadge status={d.outcome} size="sm" /></td>
						<td>{d.triggered_by || '—'}</td>
						<td class="dh-actions">
							{#if d.rollbackable}
								<button
									class="forge-btn-ghost"
									onclick={() => (confirmEntry = d)}
									disabled={rollingBack}
								>
									<IconRestart size={13} />
									<span>{$t('apps.detail.deployHistory.rollback')}</span>
								</button>
							{/if}
						</td>
					</tr>
				{/each}
			</tbody>
		</table>
	{/if}
</section>

{#if confirmEntry}
	<ConfirmDialog
		open={true}
		title={$t('apps.detail.deployHistory.confirmTitle')}
		message={$t('apps.detail.deployHistory.confirmMessage', { ref: shortRef(confirmEntry.reference) })}
		confirmLabel={$t('apps.detail.deployHistory.rollback')}
		confirmVariant="danger"
		onconfirm={() => confirmEntry && doRollback(confirmEntry)}
		oncancel={() => (confirmEntry = null)}
	/>
{/if}

<style>
	.dh-panel {
		margin-top: 1rem;
	}
	.panel-head {
		display: flex;
		align-items: baseline;
		gap: 0.5rem;
	}
	.dh-refresh {
		margin-left: auto;
	}
	.hint {
		font-size: 0.72rem;
		color: var(--text-tertiary);
		margin: 0.3rem 0;
	}
	.dh-table {
		width: 100%;
		margin-top: 0.5rem;
	}
	.reason-tag {
		font-size: 0.68rem;
		letter-spacing: 0.04em;
		text-transform: uppercase;
		color: var(--text-secondary);
	}
	.mono {
		font-family: var(--font-mono, monospace);
		font-size: 0.74rem;
	}
	.dh-actions {
		display: flex;
		justify-content: flex-end;
	}
</style>
