<!-- #region TranslationRunProgress [C:3] [TYPE Component] [SEMANTICS translate, progress, websocket, batch, status] -->
<!-- @BRIEF Component component: lib/components/translate/TranslationRunProgress.svelte -->
<!-- @RELATION DEPENDS_ON -> [TranslateApi] -->
<!-- @RELATION DEPENDS_ON -> [EXT:frontend:api_module] -->
<!-- @UX_STATE idle -> Initial state, no run loaded -->
<!-- @UX_STATE running -> Translation phase in progress -->
<!-- @UX_STATE inserting -> Insert phase in progress -->
<!-- @UX_STATE completed -> All phases completed successfully -->
<!-- @UX_STATE partial -> Translation completed with some failures -->
<!-- @UX_STATE failed -> Translation phase failed -->
<!-- @UX_STATE insert_failed -> Insert phase failed -->
<!-- @UX_STATE cancelled -> Run was cancelled -->
<!-- @UX_FEEDBACK progress bar with percentage; batch counter; per-phase counts; cancel button during running/inserting. -->
<!-- @UX_RECOVERY retry on failure states. -->
<script lang="ts">
	import { t } from '$lib/i18n/index.svelte.js';
	import { addToast } from '$lib/toasts.svelte.js';
	import { cancelRun, downloadFailedCsv } from '$lib/api/translate.js';
	import { translationRunStore } from '$lib/stores/translationRun.svelte.js';

	/** @type {{ runId: string, onRetry?: () => void, onRetryInsert?: () => void, onComplete?: (statusData: any) => void }} */
	let { runId, onRetry = () => {}, onRetryInsert = () => {}, onComplete = () => {} } = $props();

	let isCancelling = $state(false);
	let completionDelivered = $state(false);
	let storeSnapshot = $derived(translationRunStore.value?.runId === runId ? translationRunStore.value : null);

	// Derived
	let uxState = $derived(storeSnapshot?.uxState || 'idle');
	let status = $derived(storeSnapshot?.status || null);
	let totalRecords = $derived(storeSnapshot?.totalRecords || 0);
	let successfulRecords = $derived(storeSnapshot?.successfulRecords || 0);
	let failedRecords = $derived(storeSnapshot?.failedRecords || 0);
	let skippedRecords = $derived(storeSnapshot?.skippedRecords || 0);
	let progressPct = $derived(storeSnapshot?.progressPct || 0);
	let batchCount = $derived(storeSnapshot?.batchCount || 0);
	let insertStatus = $derived(storeSnapshot?.insertStatus || null);

	let isRunning = $derived(uxState === 'running' || uxState === 'inserting');

	$effect(() => {
		if (!runId) {
			completionDelivered = false;
			return;
		}
		if (isRunning || !status || completionDelivered) return;
		completionDelivered = true;
		onComplete(status);
	});

	/** @returns {Promise<void>} */
	async function handleCancel() {
		isCancelling = true;
		try {
			await cancelRun(runId);
			addToast($t.translate?.run?.run_cancelled, 'info');
		} catch (err) {
			addToast(err?.message || $t.translate?.run?.cancel_failed, 'error');
		} finally {
			isCancelling = false;
		}
	}
</script>

<div class="translation-run-progress">
	{#if uxState === 'idle'}
		<div class="bg-gray-50 border border-gray-200 rounded-lg p-4 text-center">
			<p class="text-sm text-gray-500">{$t.translate?.run?.loading}</p>
		</div>

	{:else if isRunning}
		<div class="bg-white border border-gray-200 rounded-lg p-4 space-y-3">
			<!-- Phase indicator -->
			<div class="flex items-center justify-between">
				<div class="flex items-center gap-2">
					<div class="animate-spin rounded-full h-4 w-4 border-b-2 border-blue-600" />
					<span class="text-sm font-medium text-gray-900">
						{uxState === 'inserting' ? $t.translate?.run?.insert_phase : $t.translate?.run?.translate_phase}
					</span>
				</div>
				<button
					onclick={handleCancel}
					disabled={isCancelling}
					class="px-3 py-1 text-xs border border-red-300 text-red-600 rounded hover:bg-red-50 disabled:opacity-50 transition-colors"
				>
					{isCancelling ? $t.translate?.run?.cancelling : $t.translate?.run?.cancel}
				</button>
			</div>

			<!-- Progress bar -->
			<div class="w-full bg-gray-200 rounded-full h-2.5">
				<div
					class="bg-primary h-2.5 rounded-full transition-all duration-500"
					style="width: {Math.min(progressPct, 100)}%"
				/>
			</div>

			<!-- Statistics -->
			<div class="grid grid-cols-4 gap-3 text-sm">
				<div>
					<span class="text-gray-500">{$t.translate?.run?.total}</span>
					<p class="font-semibold">{totalRecords}</p>
				</div>
				<div>
					<span class="text-green-600">{$t.translate?.run?.success}</span>
					<p class="font-semibold text-green-700">{successfulRecords}</p>
				</div>
				<div>
					<span class="text-red-600">{$t.translate?.run?.failed}</span>
					<p class="font-semibold text-red-700">{failedRecords}</p>
				</div>
				<div>
					<span class="text-yellow-600">{$t.translate?.run?.skipped}</span>
					<p class="font-semibold text-yellow-700">{skippedRecords}</p>
				</div>
			</div>

			<!-- Batch counter -->
			<p class="text-xs text-gray-400">
				{$t.translate?.run?.batches_progress?.replace('{count}', batchCount).replace('{pct}', progressPct)}
			</p>
		</div>

	<!-- Completed -->
	{:else if uxState === 'completed'}
		<div class="bg-green-50 border border-green-200 rounded-lg p-4">
			<div class="flex items-center gap-2 mb-2">
				<span class="text-green-600 text-lg">&#10003;</span>
				<span class="text-sm font-semibold text-green-800">{$t.translate?.run?.completed}</span>
			</div>
			<div class="grid grid-cols-3 gap-3 text-sm">
				<div>
					<span class="text-gray-500">{$t.translate?.run?.total}</span>
					<p class="font-semibold text-green-700">{successfulRecords} / {totalRecords}</p>
				</div>
				<div>
					<span class="text-gray-500">{$t.translate?.run?.skipped}</span>
					<p class="font-semibold">{skippedRecords}</p>
				</div>
				<div>
					<span class="text-gray-500">{$t.translate?.run?.insert_status?.replace(':', '')}</span>
					<p class="font-semibold text-green-700">{insertStatus || $t.translate?.run?.insert_completed}</p>
				</div>
			</div>
		</div>

	<!-- Partial (completed with errors) -->
	{:else if uxState === 'partial'}
		<div class="bg-yellow-50 border border-yellow-200 rounded-lg p-4">
			<div class="flex items-center justify-between mb-2">
				<div class="flex items-center gap-2">
					<span class="text-yellow-600 text-lg">&#9888;</span>
					<span class="text-sm font-semibold text-yellow-800">{$t.translate?.run?.completed_with_errors}</span>
				</div>
				<button
					onclick={onRetry}
					class="px-3 py-1 text-xs bg-yellow-100 text-yellow-700 rounded hover:bg-yellow-200 transition-colors"
				>
					{$t.translate?.run?.retry_failed}
				</button>
			</div>
			<div class="grid grid-cols-3 gap-3 text-sm">
				<div>
					<span class="text-gray-500">{$t.translate?.run?.success}</span>
					<p class="font-semibold text-green-700">{successfulRecords}</p>
				</div>
				<div>
					<span class="text-gray-500">{$t.translate?.run?.failed}</span>
					<p class="font-semibold text-red-700">{failedRecords}</p>
				</div>
				<div>
					<span class="text-gray-500">{$t.translate?.run?.skipped}</span>
					<p class="font-semibold">{skippedRecords}</p>
				</div>
			</div>
		</div>

	<!-- Failed -->
	{:else if uxState === 'failed'}
		<div class="bg-destructive-light border-destructive-light rounded-lg p-4">
			<div class="flex items-center justify-between mb-2">
				<div class="flex items-center gap-2">
					<span class="text-red-600 text-lg">&#10007;</span>
					<span class="text-sm font-semibold text-red-800">{$t.translate?.run?.translation_failed}</span>
				</div>
				<button
					onclick={onRetry}
					class="px-3 py-1 text-xs bg-red-100 text-red-700 rounded hover:bg-red-200 transition-colors"
				>
					{$t.translate?.common?.retry}
				</button>
			</div>
			<p class="text-xs text-red-600">{status?.error_message || $t.translate?.common?.unknown}</p>
		</div>

	<!-- Insert Failed -->
	{:else if uxState === 'insert_failed'}
		<div class="bg-orange-50 border border-orange-200 rounded-lg p-4">
			<div class="flex items-center justify-between mb-2">
				<div class="flex items-center gap-2">
					<span class="text-orange-600 text-lg">&#9888;</span>
					<span class="text-sm font-semibold text-orange-800">{$t.translate?.run?.insert_failed}</span>
				</div>
				<div class="flex items-center gap-2">
					<button
						onclick={async () => {
							try { await downloadFailedCsv(runId); }
							catch (e) { addToast(e?.message || 'Download failed', 'error'); }
						}}
						class="px-3 py-1 text-xs bg-blue-100 text-blue-700 rounded hover:bg-blue-200 transition-colors"
					>
						{$t.translate?.run?.download_csv || 'Download CSV'}
					</button>
					<button
						onclick={onRetryInsert}
						class="px-3 py-1 text-xs bg-orange-100 text-orange-700 rounded hover:bg-orange-200 transition-colors"
					>
						{$t.translate?.run?.retry_insert}
					</button>
				</div>
			</div>
			<p class="text-xs text-gray-600 mt-1">
				{$t.translate?.run?.completed} ({successfulRecords}) &mdash; {$t.translate?.run?.insert_failed}
			</p>
		</div>

	<!-- Cancelled -->
	{:else if uxState === 'cancelled'}
		<div class="bg-gray-50 border border-gray-200 rounded-lg p-4">
			<div class="flex items-center gap-2">
				<span class="text-gray-500 text-lg">&#9632;</span>
				<span class="text-sm font-semibold text-gray-700">{$t.translate?.run?.cancelled}</span>
			</div>
		</div>
	{/if}
</div>
<!-- #endregion TranslationRunProgress -->
