<!-- #region DashboardValidationPage [C:3] [TYPE Page] [SEMANTICS dashboards,validation,history,run-list] -->
<!-- @ingroup Routes -->
<!-- @BRIEF Validation runs history for a single dashboard — paginated table with status, date, summary, and report links. -->
<!-- @LAYER Page -->
<!-- @RELATION DEPENDS_ON -> [I18nModule] -->
<!-- @RELATION CALLS -> [fetchApi] -->
<!-- @UX_STATE Loading -> Skeleton table rows -->
<!-- @UX_STATE Loaded -> Data rows with all columns -->
<!-- @UX_STATE Empty -> Centered empty state message -->
<!-- @UX_STATE Error -> Red banner with error details and retry link -->
<!-- @UX_FEEDBACK Links to dashboard detail and individual run reports -->
<script lang="ts">
import { SvelteURLSearchParams } from "svelte/reactivity";
	import { goto } from '$app/navigation';
	import { ROUTES } from '$lib/routes.js';
	import { t } from '$lib/i18n/index.svelte.js';

	/** @type {{ data: import('./$types').PageData }} */
	let { data } = $props();

	let runs = $state(data.runs ?? []);
	let total = $state(data.total ?? 0);
	let currentPage = $state(data.page ?? 1);
	let pageSize = $state(data.page_size ?? 20);
	let dashboardId = $state(data.dashboardId);
	let envId = $state(data.envId);
	let error = $state(data.error ?? null);
	let loading = $state(false);

	const totalPages = $derived(Math.ceil(total / pageSize) || 1);

	function getStatusBadge(status: string): string {
		const map: Record<string, string> = {
			PASS: 'bg-success-light text-success',
			WARN: 'bg-warning-light text-warning',
			FAIL: 'bg-destructive-light text-destructive',
			UNKNOWN: 'bg-surface-muted text-text-muted',
			RUNNING: 'bg-primary-light text-primary',
			PENDING: 'bg-warning-light text-warning',
			SUCCESS: 'bg-success-light text-success',
			ERROR: 'bg-destructive-light text-destructive',
		};
		return map[status?.toUpperCase()] || 'bg-surface-muted text-text-muted';
	}

	function formatDate(ts: string | null): string {
		if (!ts) return '—';
		try {
			return new Date(ts).toLocaleString();
		} catch {
			return String(ts);
		}
	}

	function formatDuration(started: string | null, finished: string | null): string {
		if (!started) return '—';
		const start = new Date(started).getTime();
		const end = finished ? new Date(finished).getTime() : Date.now();
		const ms = end - start;
		if (ms < 1000) return `${ms}ms`;
		if (ms < 60000) return `${(ms / 1000).toFixed(1)}s`;
		return `${Math.floor(ms / 60000)}m ${Math.floor((ms % 60000) / 1000)}s`;
	}

	function getRunLink(run: any): string | null {
		const policyId = run.policy_id || run.policyId;
		const runId = run.id || run.run_id;
		if (policyId && runId) {
			return ROUTES.validationTasks.runReport(policyId, runId);
		}
		if (policyId) {
			return ROUTES.validationTasks.detail(policyId);
		}
		return null;
	}

	function viewRun(run: any) {
		const link = getRunLink(run);
		if (link) goto(link);
	}

	function goBack() {
		goto(ROUTES.dashboards.detail(dashboardId, envId));
	}

	async function loadPage() {
		loading = true;
		error = null;
		try {
			const qs = new SvelteURLSearchParams();
			qs.append('dashboard_id', dashboardId);
			qs.append('environment_id', envId);
			qs.append('page', String(currentPage));
			qs.append('page_size', String(pageSize));

			const { fetchApi } = await import('$lib/api');
			const result = await fetchApi(`/validation-tasks/runs/all?${qs.toString()}`);
			runs = result?.items ?? result?.results ?? [];
			total = result?.total ?? 0;
		} catch (e) {
			error = e instanceof Error ? e.message : 'Failed to load runs';
		} finally {
			loading = false;
		}
	}

	function goToPage(p: number) {
		if (p < 1 || p > totalPages) return;
		currentPage = p;
		loadPage();
	}
</script>

<svelte:head>
	<title>{$t.dashboard?.validation_history || 'Dashboard Validation'} — {dashboardId}</title>
</svelte:head>

<div class="max-w-7xl mx-auto px-4 py-6">
	<!-- Header -->
	<div class="flex items-center justify-between mb-6">
		<div class="flex items-center gap-3">
			<button
				onclick={goBack}
				class="inline-flex items-center gap-1 text-sm text-text-muted hover:text-text transition-colors"
				aria-label={$t.common?.back || 'Back'}
			>
				<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
					<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7" />
				</svg>
				{$t.common?.back || 'Back'}
			</button>
			<div class="h-5 w-px bg-surface-muted"></div>
			<h1 class="text-2xl font-bold text-text">
				{$t.dashboard?.validation_history || 'Validation History'}
			</h1>
		</div>
		<div class="flex items-center gap-2 text-sm text-text-muted">
			<span class="font-mono text-xs bg-surface-muted px-2 py-1 rounded">{dashboardId}</span>
			<span class="font-mono text-xs bg-surface-muted px-2 py-1 rounded">{envId}</span>
		</div>
	</div>

	<!-- Error state -->
	{#if error && !loading}
		<div class="bg-destructive-light border border-destructive-ring rounded-lg p-4 mb-6 flex items-center justify-between" role="alert">
			<div class="flex items-center gap-2 text-destructive text-sm">
				<svg class="w-5 h-5 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
					<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
				</svg>
				<span>{error}</span>
			</div>
			<button
				onclick={goBack}
				class="px-3 py-1.5 text-sm bg-surface-muted text-white rounded-lg hover:bg-terminal-bg transition-colors"
			>
				{$t.common?.back || 'Back to Dashboard'}
			</button>
		</div>
	{/if}

	<!-- Missing env_id -->
	{#if !envId && !loading}
		<div class="bg-warning-light border border-warning rounded-lg p-4 mb-6 text-sm text-warning" role="alert">
			{$t.dashboard?.missing_context || 'Environment context is missing. Please select an environment to view validation history.'}
		</div>
	{/if}

	<!-- Loading -->
	{#if loading}
		<div class="bg-surface-card border border-border rounded-lg overflow-hidden">
			<table class="min-w-full divide-y divide-border">
				<thead class="bg-surface-muted">
					<tr>
						<th class="px-4 py-3 text-left text-xs font-medium text-text-muted uppercase tracking-wider">{$t.validation?.status || 'Status'}</th>
						<th class="px-4 py-3 text-left text-xs font-medium text-text-muted uppercase tracking-wider">{$t.validation?.started || 'Started'}</th>
						<th class="px-4 py-3 text-left text-xs font-medium text-text-muted uppercase tracking-wider">{$t.validation?.duration || 'Duration'}</th>
						<th class="px-4 py-3 text-left text-xs font-medium text-text-muted uppercase tracking-wider">{$t.validation?.summary || 'Summary'}</th>
						<th class="px-4 py-3 text-left text-xs font-medium text-text-muted uppercase tracking-wider">{$t.validation?.task_name || 'Task'}</th>
						<th class="px-4 py-3 text-right text-xs font-medium text-text-muted uppercase tracking-wider">{$t.common?.actions || 'Actions'}</th>
					</tr>
				</thead>
				<tbody class="bg-surface-card divide-y divide-border">
					{#each Array(5) as _, i (i)}
						<tr class="animate-pulse">
							<td class="px-4 py-3"><div class="h-5 w-16 bg-surface-muted rounded-full"></div></td>
							<td class="px-4 py-3"><div class="h-4 w-32 bg-surface-muted rounded"></div></td>
							<td class="px-4 py-3"><div class="h-4 w-16 bg-surface-muted rounded"></div></td>
							<td class="px-4 py-3"><div class="h-4 w-48 bg-surface-muted rounded"></div></td>
							<td class="px-4 py-3"><div class="h-4 w-24 bg-surface-muted rounded"></div></td>
							<td class="px-4 py-3"><div class="h-4 w-16 bg-surface-muted rounded ml-auto"></div></td>
						</tr>
					{/each}
				</tbody>
			</table>
		</div>

	<!-- Empty -->
	{:else if runs.length === 0}
		<div class="bg-surface-card border border-dashed border-border-strong rounded-lg p-12 text-center">
			<svg class="w-16 h-16 mx-auto text-text-subtle mb-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
				<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
			</svg>
			<p class="text-text-muted text-sm mb-1">{$t.dashboard?.no_validation_runs || 'No validation runs found for this dashboard.'}</p>
			<p class="text-text-subtle text-xs mb-4">{$t.dashboard?.validation_history_info || 'Validation runs appear here after an LLM validation check has been performed.'}</p>
			<button
				onclick={goBack}
				class="inline-flex items-center px-4 py-2 bg-surface-muted text-white rounded-lg hover:bg-terminal-bg transition-colors text-sm font-medium"
			>
				{$t.common?.back || 'Back to Dashboard'}
			</button>
		</div>

	<!-- Loaded: table -->
	{:else}
		<div class="bg-surface-card border border-border rounded-lg shadow-sm overflow-hidden">
			<div class="overflow-x-auto">
				<table class="min-w-full divide-y divide-border">
					<thead class="bg-surface-muted">
						<tr>
							<th class="px-4 py-3 text-left text-xs font-medium text-text-muted uppercase tracking-wider">{$t.validation?.status || 'Status'}</th>
							<th class="px-4 py-3 text-left text-xs font-medium text-text-muted uppercase tracking-wider">{$t.validation?.started || 'Started'}</th>
							<th class="px-4 py-3 text-left text-xs font-medium text-text-muted uppercase tracking-wider">{$t.validation?.duration || 'Duration'}</th>
							<th class="px-4 py-3 text-left text-xs font-medium text-text-muted uppercase tracking-wider">{$t.validation?.summary || 'Summary'}</th>
							<th class="px-4 py-3 text-left text-xs font-medium text-text-muted uppercase tracking-wider">{$t.validation?.task_name || 'Task'}</th>
							<th class="px-4 py-3 text-right text-xs font-medium text-text-muted uppercase tracking-wider">{$t.common?.actions || 'Actions'}</th>
						</tr>
					</thead>
					<tbody class="divide-y divide-border">
						{#each runs as run (run.id || run.run_id)}
							{@const runLink = getRunLink(run)}
							{@const normalizedStatus = String(run.status || run.validation_status || '').toUpperCase()}
							<tr
								class="{runLink ? 'hover:bg-surface-muted cursor-pointer' : ''} transition-colors"
								onclick={runLink ? () => viewRun(run) : undefined}
								role={runLink ? 'button' : undefined}
								tabindex={runLink ? 0 : undefined}
								onkeydown={runLink ? (e) => { if (e.key === 'Enter') viewRun(run); } : undefined}
							>
								<td class="px-4 py-3">
									<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium {getStatusBadge(normalizedStatus)}">
										{normalizedStatus || 'UNKNOWN'}
									</span>
								</td>
								<td class="px-4 py-3 text-sm text-text whitespace-nowrap">
									{formatDate(run.started_at || run.timestamp || run.created_at)}
								</td>
								<td class="px-4 py-3 text-sm text-text-muted whitespace-nowrap">
									{formatDuration(run.started_at, run.finished_at)}
								</td>
								<td class="px-4 py-3 text-sm text-text-muted max-w-xs truncate">
									{run.summary || run.description || '—'}
								</td>
								<td class="px-4 py-3 text-sm text-text-muted whitespace-nowrap">
									{#if run.policy_name || run.policyId || run.policy_id}
										<span class="text-xs font-medium text-primary">{run.policy_name || run.policyId || run.policy_id}</span>
									{:else}
										<span class="text-text-subtle">—</span>
									{/if}
								</td>
								<td class="px-4 py-3 text-right whitespace-nowrap">
									{#if runLink}
										<a
											href={runLink}
											class="inline-flex items-center gap-1 text-xs font-medium text-primary hover:text-primary transition-colors"
										>
											{$t.common?.view_report || 'Report'}
											<svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
												<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
											</svg>
										</a>
									{:else}
										<span class="text-xs text-text-subtle">—</span>
									{/if}
								</td>
							</tr>
						{/each}
					</tbody>
				</table>
			</div>
		</div>

		<!-- Pagination -->
		{#if totalPages > 1}
			<div class="flex items-center justify-between mt-4">
				<p class="text-sm text-text-muted">
					{($t.validation?.showing || 'Showing {from}-{to} of {total}')
						.replace('{from}', String((currentPage - 1) * pageSize + 1))
						.replace('{to}', String(Math.min(currentPage * pageSize, total)))
						.replace('{total}', String(total))}
				</p>
				<nav class="flex items-center gap-1" aria-label="Pagination">
					<button
						onclick={() => goToPage(currentPage - 1)}
						disabled={currentPage <= 1}
						class="px-3 py-1.5 text-sm border border-border-strong rounded-lg disabled:opacity-40 disabled:cursor-not-allowed hover:bg-surface-muted text-text-muted transition-colors"
					>
						{$t.validation?.previous || 'Previous'}
					</button>
					{#each Array.from({ length: Math.min(totalPages, 7) }, (_, i) => {
						if (totalPages <= 7) return i + 1;
						const half = 3;
						const start = Math.max(1, currentPage - half);
						const end = Math.min(totalPages, start + 6);
						const adjustedStart = Math.max(1, end - 6);
						return adjustedStart + i;
					}) as p (p)}
						<button
							onclick={() => goToPage(p)}
							class="px-3 py-1.5 text-sm border rounded-lg transition-colors {p === currentPage ? 'bg-primary-light border-primary-ring text-primary' : 'border-border text-text-muted hover:bg-surface-muted'}"
						>
							{p}
						</button>
					{/each}
					<button
						onclick={() => goToPage(currentPage + 1)}
						disabled={currentPage >= totalPages}
						class="px-3 py-1.5 text-sm border border-border-strong rounded-lg disabled:opacity-40 disabled:cursor-not-allowed hover:bg-surface-muted text-text-muted transition-colors"
					>
						{$t.validation?.next || 'Next'}
					</button>
				</nav>
			</div>
		{/if}
	{/if}
</div>
<!-- #endregion DashboardValidationPage -->
