<script lang="ts">
	import * as Dialog from '$lib/components/ui/dialog/index.js';
	import { Button } from '$lib/components/ui/button/index.js';
	import {
		Loader2,
		CheckCircle2,
		AlertTriangle,
		XCircle,
		FileText,
		UploadCloud
	} from 'lucide-svelte';
	import { tick } from 'svelte';
	import { api } from '$lib/api';
	import {
		totalSkippedFromCommit,
		criticalReferenceGaps,
		referenceStateReady
	} from '$lib/csv-import-commit-metrics';
	import { csvFmt, csvMsg } from '$lib/i18n/csv-msg';

	let {
		open = $bindable(false),
		scanResults = null,
		commitResults = null,
		isUploading = false,
		scanErrorsDownloadType = 'imports',
		onConfirm,
		onCancel,
		onClose
	}: {
		open: boolean;
		scanResults: any;
		commitResults: any;
		isUploading: boolean;
		scanErrorsDownloadType?:
			| 'imports'
			| 'exportacion'
			| 'customs_brokers'
			| 'clients_providers'
			| 'exchange_rate'
			| 'pedimentos'
			| 'classes'
			| 'vehicles'
			| 'drivers'
			| 'trailers'
			| 'transporters'
			| 'parts'
			| 'boms';
		onConfirm: () => void;
		onCancel: () => void;
		onClose: () => void;
	} = $props();

	// Determine state
	let isPending = $derived(!!scanResults && !commitResults);
	let isFinished = $derived(!!commitResults);

	let scanErrorsShown = $derived(Array.isArray(scanResults?.errors) ? scanResults.errors.length : 0);
	let scanErrorsTotal = $derived(scanResults?.error_count || 0);
	let scanErrorsTruncated = $derived(scanErrorsShown > 0 && scanErrorsShown < scanErrorsTotal);

	let scanErrorSummary = $derived(
		Array.isArray(scanResults?.error_summary) ? scanResults.error_summary : []
	);

	let totalSkipped = $derived(totalSkippedFromCommit(commitResults));
	let refGaps = $derived(criticalReferenceGaps(commitResults));
	let refReady = $derived(referenceStateReady(commitResults));

	let insertedCount = $derived(Number(commitResults?.inserted) || 0);
	let updatedCount = $derived(Number(commitResults?.updated) || 0);

	/** Cabecera: errores de escaneo (solo pendiente) o observaciones de commit. */
	let hasErrors = $derived(
		(isPending && (scanResults?.error_count ?? 0) > 0) ||
			(isFinished &&
				(totalSkipped > 0 ||
					refGaps > 0 ||
					commitResults?.status === 'warning'))
	);

	let commitSkippedSummary = $derived(
		Array.isArray(commitResults?.skipped_summary) ? commitResults.skipped_summary : []
	);

	function handleOpenChange(newOpen: boolean) {
		if (!newOpen) {
			if (isPending) onCancel();
			else onClose();
		}
		open = newOpen;
	}

	function csvEscape(value: unknown): string {
		const s = value === null || value === undefined ? '' : String(value);
		// Quote fields when they contain CSV-breaking characters.
		if (/[",\n\r]/.test(s)) return `"${s.replace(/"/g, '""')}"`;
		return s;
	}

	function downloadCsv(filename: string, headers: string[], rows: Array<Record<string, unknown>>, columns: string[]) {
		const delimiter = ','; // CSV por comas
		const lines: string[] = [];
		lines.push(headers.map(csvEscape).join(delimiter));
		for (const r of rows) {
			lines.push(columns.map((k) => csvEscape(r?.[k])).join(delimiter));
		}
		const blob = new Blob([lines.join('\n')], { type: 'text/csv;charset=utf-8' });
		const url = URL.createObjectURL(blob);
		const a = document.createElement('a');
		a.href = url;
		a.download = filename;
		document.body.appendChild(a);
		a.click();
		document.body.removeChild(a);
		URL.revokeObjectURL(url);
	}

	async function handleDownloadScanErrorsCsv() {
		const errors = scanResults?.errors;
		if (!Array.isArray(errors) || errors.length === 0) return;

		const jobId = scanResults?.job_id;

		// Try backend download (sin límite). If it fails, fallback to preview CSV.
		if (jobId) {
			try {
				let blob: Blob;
				switch (scanErrorsDownloadType) {
					case 'exportacion':
						blob = await api.exportacionImports.downloadScanErrorsCsv(jobId);
						break;
					case 'customs_brokers':
						blob = await api.customsBrokerImports.downloadScanErrorsCsv(jobId);
						break;
					case 'clients_providers':
						blob = await api.clientProviderImports.downloadScanErrorsCsv(jobId);
						break;
					case 'exchange_rate':
						blob = await api.exchangeRateImports.downloadScanErrorsCsv(jobId);
						break;
					case 'pedimentos':
						blob = await api.pedimentosImports.downloadScanErrorsCsv(jobId);
						break;
					case 'classes':
						blob = await api.materialClassImports.downloadScanErrorsCsv(jobId);
						break;
					case 'vehicles':
						blob = await api.vehicleImports.downloadScanErrorsCsv(jobId);
						break;
					case 'drivers':
						blob = await api.driverImports.downloadScanErrorsCsv(jobId);
						break;
					case 'trailers':
						blob = await api.trailerImports.downloadScanErrorsCsv(jobId);
						break;
					case 'transporters':
						blob = await api.transporterImports.downloadScanErrorsCsv(jobId);
						break;
					case 'parts':
						blob = await api.partNumberImports.downloadScanErrorsCsv(jobId);
						break;
					case 'boms':
						blob = await api.bomImports.downloadScanErrorsCsv(jobId);
						break;
					case 'imports':
					default:
						blob = await api.imports.downloadScanErrorsCsv(jobId);
						break;
				}

				const url = URL.createObjectURL(blob);
				const a = document.createElement('a');
				a.href = url;
				a.download = `errores_${jobId}.csv`;
				document.body.appendChild(a);
				a.click();
				document.body.removeChild(a);
				URL.revokeObjectURL(url);
				return;
			} catch (e) {
				// fallback below
			}
		}

		const filename = `errores_${Date.now()}.csv`;
		downloadCsv(
			filename,
			['linea', 'columna', 'mensaje', 'solucion'],
			errors,
			['line', 'col', 'msg', 'solution']
		);
	}

	function handleDownloadCommitSkippedDetailsCsv() {
		const details = commitResults?.skipped_details;
		if (!Array.isArray(details) || details.length === 0) return;

		// Table columns: line, invoice, reason, solution
		const filename = `errores_importacion_${Date.now()}.csv`;
		downloadCsv(
			filename,
			['linea', 'referencia', 'motivo', 'solucion'],
			details,
			['line', 'invoice', 'reason', 'solution']
		);
	}

	// When modal shows finished state with rejection details, scroll the detail table into view
	$effect(() => {
		if (open && isFinished && commitResults?.skipped_details?.length > 0) {
			tick().then(() => {
				const el = document.getElementById('detalle-errores-import');
				el?.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
			});
		}
	});
</script>

<Dialog.Root bind:open onOpenChange={handleOpenChange}>
	<Dialog.Content
		class="sm:max-w-[650px] p-0 gap-0 overflow-hidden border-0 shadow-xl flex flex-col max-h-[90vh] bg-background text-foreground"
	>
		<!-- Header Section with Theme Colors -->
		<div
			class="px-6 py-5 border-b flex items-start gap-4
			{isPending
				? 'bg-primary/5'
				: isFinished && !hasErrors
					? 'bg-green-50/50 dark:bg-green-900/10'
					: 'bg-destructive/5'}"
		>
			<div
				class="p-2 rounded-full ring-1 ring-inset
				{isPending
					? 'bg-primary/10 text-primary ring-primary/20'
					: isFinished && !hasErrors
						? 'bg-green-100 text-green-700 ring-green-200 dark:bg-green-900/20 dark:text-green-400 dark:ring-green-900/40'
						: 'bg-destructive/10 text-destructive ring-destructive/20'}"
			>
				{#if isPending}
					<FileText class="w-6 h-6" />
				{:else if isFinished && !hasErrors}
					<CheckCircle2 class="w-6 h-6" />
				{:else}
					<AlertTriangle class="w-6 h-6" />
				{/if}
			</div>

			<div class="flex-1">
				<Dialog.Title class="text-xl font-semibold tracking-tight text-foreground">
					{#if isPending}
						{csvMsg('modal.title_pending')}
					{:else if isFinished}
						{hasErrors ? csvMsg('modal.title_warning') : csvMsg('modal.title_success')}
					{/if}
				</Dialog.Title>
				<Dialog.Description class="mt-1 text-muted-foreground">
					{#if isPending}
						{csvMsg('modal.desc_pending')}
					{:else if isFinished}
						{csvMsg('modal.desc_done')}
					{/if}
				</Dialog.Description>
			</div>
		</div>

		<!-- Scrollable Content -->
		<div class="px-6 py-6 overflow-y-auto">
			<!-- PENDING STATE CONTENT -->
			{#if isPending}
				<div class="grid grid-cols-1 sm:grid-cols-3 gap-4 mb-6">
					<!-- Card: Total -->
					<div
						class="bg-card p-4 rounded-lg border flex flex-col items-center justify-center text-center shadow-sm"
					>
						<span class="text-muted-foreground text-xs uppercase font-bold tracking-wider mb-1"
							>{csvMsg('modal.total_rows')}</span
						>
						<span class="text-2xl font-bold text-foreground">{scanResults.total_rows || 0}</span>
					</div>

					<!-- Card: Valid -->
					<div
						class="bg-green-50/50 dark:bg-green-900/10 p-4 rounded-lg border border-green-100 dark:border-green-900/30 flex flex-col items-center justify-center text-center shadow-sm"
					>
						<span
							class="text-green-600 dark:text-green-400 text-xs uppercase font-bold tracking-wider mb-1"
							>{csvMsg('modal.valid_rows')}</span
						>
						<span class="text-2xl font-bold text-green-700 dark:text-green-300"
							>{scanResults.valid_rows || 0}</span
						>
					</div>

					<!-- Card: Errors -->
					<div
						class="bg-destructive/5 p-4 rounded-lg border border-destructive/10 flex flex-col items-center justify-center text-center shadow-sm"
					>
						<span class="text-destructive text-xs uppercase font-bold tracking-wider mb-1"
							>{csvMsg('modal.errors')}</span
						>
						<span class="text-2xl font-bold text-destructive">{scanResults.error_count || 0}</span>
					</div>
				</div>

				{#if scanResults.message}
					<p class="mb-4 rounded-md border border-border bg-muted/30 px-3 py-2 text-sm text-foreground">
						{scanResults.message}
					</p>
				{/if}
				{#if scanErrorSummary.length > 0}
					<div class="mb-4 flex flex-wrap gap-2">
						{#each scanErrorSummary as item}
							<span
								class="inline-flex items-center rounded-full border border-border bg-secondary/60 px-2.5 py-0.5 text-xs text-secondary-foreground"
							>
								{(item as { reason?: string; count?: number }).reason ?? '—'} · {(item as { count?: number })
									.count ?? 0}
							</span>
						{/each}
					</div>
				{/if}

				{#if scanResults.error_count > 0}
					<div
						class="rounded-md bg-destructive/5 border border-destructive/10 p-4 flex items-start gap-3 mb-4"
					>
						<XCircle class="w-5 h-5 text-destructive mt-0.5 shrink-0" />
						<div class="text-sm text-destructive-foreground/90">
							<p class="font-semibold mb-1">{csvMsg('modal.scan_problems_title')}</p>
							<p>
								{csvMsg('modal.scan_problems_body')}
							</p>
						</div>
					</div>
				{#if scanResults.errors && scanResults.errors.length > 0}
					<div class="border rounded-lg overflow-hidden shadow-sm">
						<div class="bg-muted/50 px-4 py-2 border-b flex justify-between items-center">
							<h5 class="text-xs font-bold text-foreground uppercase tracking-wide">
								{csvMsg('modal.errors_heading')}
							</h5>
							<div class="flex items-center gap-2">
								<span
									class="text-[10px] bg-secondary text-secondary-foreground px-2 py-0.5 rounded-full border"
								>
									{csvFmt('modal.errors_badge', { shown: scanErrorsShown, total: scanErrorsTotal })}
								</span>
								<Button
									variant="ghost"
									onclick={handleDownloadScanErrorsCsv}
									class="h-7 px-2 text-xs"
								>
									<FileText class="w-3.5 h-3.5 mr-1" />
									{csvMsg('modal.download_csv')}
								</Button>
							</div>
						</div>
						<div class="max-h-60 overflow-y-auto bg-card relative">
							<table class="w-full text-xs text-left">
								<thead
									class="text-muted-foreground font-medium bg-muted/30 sticky top-0 z-10 shadow-sm backdrop-blur-sm"
								>
									<tr>
										<th class="px-4 py-2 w-16">{csvMsg('modal.th_line')}</th>
										<th class="px-4 py-2 w-40">{csvMsg('modal.th_column')}</th>
										<th class="px-4 py-2">{csvMsg('modal.th_message')}</th>
									<th class="px-4 py-2 min-w-[240px]">{csvMsg('modal.th_solution')}</th>
									</tr>
								</thead>
								<tbody class="divide-y">
									{#each scanResults.errors as err}
										<tr class="hover:bg-muted/30 transition-colors {err.warning ? 'opacity-70' : ''}">
											<td class="px-4 py-2 font-mono text-muted-foreground">{err.line}</td>
											<td class="px-4 py-2 font-mono font-medium text-foreground">{err.col || '-'}</td>
											<td class="px-4 py-2 {err.warning ? 'text-amber-600 dark:text-amber-400' : 'text-destructive'}">{err.msg || '-'}</td>
										<td class="px-4 py-2 text-muted-foreground whitespace-pre-wrap">{err.solution || '-'}</td>
										</tr>
									{/each}
								</tbody>
							</table>
						</div>
						{#if scanErrorsTruncated}
							<p class="text-xs text-muted-foreground px-4 py-2">
								{csvMsg('modal.errors_truncated')}
							</p>
						{/if}
					</div>
				{:else}
					<p class="text-sm text-muted-foreground mt-1">
						{csvFmt('modal.errors_missing_detail', { count: scanResults.error_count })}
					</p>
				{/if}
				{:else}
					<div class="rounded-md bg-primary/5 border border-primary/10 p-4 flex items-start gap-3">
						<CheckCircle2 class="w-5 h-5 text-primary mt-0.5 shrink-0" />
						<div class="text-sm text-primary/90">
							<p class="font-semibold mb-1">{csvMsg('modal.scan_ok_title')}</p>
							<p>{csvMsg('modal.scan_ok_body')}</p>
						</div>
					</div>
				{/if}
			{/if}

			<!-- FINISHED STATE CONTENT -->
			{#if isFinished}
				<div class="space-y-6">
					<div class="grid grid-cols-1 gap-4 sm:grid-cols-3">
						<div
							class="flex flex-col items-center justify-center rounded-lg border border-green-100 bg-green-50/50 p-4 text-center shadow-sm dark:border-green-900/30 dark:bg-green-900/10"
						>
							<div class="mb-1 flex items-center gap-2">
								<CheckCircle2 class="h-4 w-4 text-green-600 dark:text-green-400" />
								<span
									class="text-xs font-bold uppercase tracking-wider text-green-600 dark:text-green-400"
									>{csvMsg('modal.inserted')}</span
								>
							</div>
							<span class="text-3xl font-bold text-green-700 dark:text-green-300">{insertedCount}</span>
						</div>
						<div
							class="flex flex-col items-center justify-center rounded-lg border border-green-100 bg-green-50/50 p-4 text-center shadow-sm dark:border-green-900/30 dark:bg-green-900/10"
						>
							<div class="mb-1 flex items-center gap-2">
								<CheckCircle2 class="h-4 w-4 text-green-600 dark:text-green-400" />
								<span
									class="text-xs font-bold uppercase tracking-wider text-green-600 dark:text-green-400"
									>{csvMsg('modal.updated')}</span
								>
							</div>
							<span class="text-3xl font-bold text-green-700 dark:text-green-300">{updatedCount}</span>
						</div>
						<div
							class="flex flex-col items-center justify-center rounded-lg border border-destructive/10 bg-destructive/5 p-4 text-center shadow-sm"
						>
							<div class="mb-1 flex items-center gap-2">
								<XCircle class="h-4 w-4 text-destructive" />
								<span class="text-xs font-bold uppercase tracking-wider text-destructive"
									>{csvMsg('modal.rejected')}</span
								>
							</div>
							<span class="text-3xl font-bold text-destructive">{totalSkipped}</span>
							{#if totalSkipped > 0 && commitResults.skipped_details && commitResults.skipped_details.length > 0}
								<p class="mt-2 text-xs text-muted-foreground">
									{csvMsg('modal.rejected_hint')}
								</p>
							{/if}
						</div>
					</div>

					<div
						class="flex items-start gap-3 rounded-md border p-3 text-sm {refGaps > 0
							? 'border-amber-500/40 bg-amber-500/10'
							: 'border-border bg-muted/30'}"
					>
						{#if refGaps > 0}
							<AlertTriangle class="mt-0.5 h-5 w-5 shrink-0 text-amber-600 dark:text-amber-500" />
							<div>
								<p class="font-semibold text-foreground">{csvMsg('modal.ref_gaps_title')}</p>
								<p class="mt-1 text-muted-foreground">
									{csvFmt('modal.ref_gaps_body', { n: refGaps })}
								</p>
							</div>
						{:else}
							<CheckCircle2 class="mt-0.5 h-5 w-5 shrink-0 text-green-600 dark:text-green-500" />
							<div>
								<p class="font-semibold text-foreground">{csvMsg('modal.ref_state_title')}</p>
								<p class="mt-1 text-muted-foreground">
									{refReady ? csvMsg('modal.ref_state_ok') : csvMsg('modal.ref_state_other')}
								</p>
							</div>
						{/if}
					</div>

					{#if commitResults.message}
						<p class="rounded-md border border-border bg-muted/30 px-3 py-2 text-sm text-foreground">
							{commitResults.message}
						</p>
					{/if}
					{#if commitSkippedSummary.length > 0}
						<div>
							<p class="mb-2 text-xs font-bold uppercase tracking-wide text-muted-foreground">
								{csvMsg('modal.skipped_reasons_heading')}
							</p>
							<div class="flex flex-wrap gap-2">
								{#each commitSkippedSummary as item}
									<span
										class="inline-flex items-center rounded-full border border-border bg-secondary/60 px-2.5 py-0.5 text-xs text-secondary-foreground"
									>
										{(item as { reason?: string; count?: number }).reason ?? '—'} · {(item as {
											count?: number;
										}).count ?? 0}
									</span>
								{/each}
							</div>
						</div>
					{/if}

					<!-- Error Details Table -->
					{#if commitResults.skipped_details && commitResults.skipped_details.length > 0}
						<div id="detalle-errores-import" class="border rounded-lg overflow-hidden mt-2 shadow-sm">
							<div class="bg-muted/50 px-4 py-2 border-b flex justify-between items-center">
								<h5 class="text-xs font-bold text-foreground uppercase tracking-wide">
									{csvMsg('modal.commit_errors_heading')}
								</h5>
						<div class="flex items-center gap-2">
							<span
								class="text-[10px] bg-secondary text-secondary-foreground px-2 py-0.5 rounded-full border"
							>
								{csvFmt('modal.rows_badge', { n: commitResults.skipped_details.length })}
							</span>
							<Button
								variant="ghost"
								onclick={handleDownloadCommitSkippedDetailsCsv}
								class="h-7 px-2 text-xs"
							>
								<FileText class="w-3.5 h-3.5 mr-1" />
								{csvMsg('modal.download_csv')}
							</Button>
						</div>
							</div>
							<div class="max-h-60 overflow-y-auto bg-card relative">
								<table class="w-full text-xs text-left">
									<thead
										class="text-muted-foreground font-medium bg-muted/30 sticky top-0 z-10 shadow-sm backdrop-blur-sm"
									>
										<tr>
											<th class="px-4 py-2 w-20">{csvMsg('modal.th_line')}</th>
											<th class="px-4 py-2 w-32">{csvMsg('modal.th_reference')}</th>
											<th class="px-4 py-2">{csvMsg('modal.th_reason')}</th>
											<th class="px-4 py-2 min-w-[240px]">{csvMsg('modal.th_solution')}</th>
										</tr>
									</thead>
									<tbody class="divide-y">
										{#each commitResults.skipped_details as detail}
											<tr class="hover:bg-muted/30 transition-colors">
												<td class="px-4 py-2 font-mono text-muted-foreground">{detail.line}</td>
												<td class="px-4 py-2 font-mono font-medium text-foreground"
													>{detail.invoice || '-'}</td
												>
												<td class="px-4 py-2 text-destructive">{detail.reason ?? '-'}</td>
												<td class="px-4 py-2 text-muted-foreground whitespace-pre-wrap">{detail.solution || '-'}</td>
											</tr>
										{/each}
									</tbody>
								</table>
							</div>
						</div>
					{/if}
				</div>
			{/if}
		</div>

		<!-- Footer Actions -->
		<div class="flex flex-col gap-3 border-t bg-muted/20 px-6 py-4">
			{#if isPending && isUploading}
				<div class="space-y-2" role="status" aria-live="polite" aria-busy="true">
					<p class="text-xs font-medium text-muted-foreground">{csvMsg('modal.importing_records')}</p>
					<div class="relative h-2 w-full overflow-hidden rounded-full bg-secondary">
						<div
							class="csv-commit-indeterminate-bar absolute top-0 h-full w-2/5 rounded-full bg-primary"
						/>
					</div>
				</div>
			{/if}
			<div class="flex items-center justify-end gap-3">
				{#if isPending}
					<Button
						variant="ghost"
						onclick={onCancel}
						disabled={isUploading}
						class="text-muted-foreground hover:bg-muted/50"
					>
						{csvMsg('modal.cancel_operation')}
					</Button>
					<Button
						onclick={onConfirm}
						disabled={isUploading}
						class="min-w-[140px] bg-primary text-primary-foreground shadow-sm hover:bg-primary/90"
					>
						{#if isUploading}
							<Loader2 class="mr-2 h-4 w-4 animate-spin" />
							{csvMsg('modal.processing')}
						{:else}
							<UploadCloud class="mr-2 h-4 w-4" />
							{csvMsg('modal.confirm_load')}
						{/if}
					</Button>
				{:else if isFinished}
					<Button variant="outline" onclick={onClose} class="min-w-[100px]">{csvMsg('modal.close')}</Button>
				{/if}
			</div>
		</div>
	</Dialog.Content>
</Dialog.Root>

<style>
	@keyframes csv-commit-indeterminate {
		0% {
			transform: translateX(-100%);
		}
		100% {
			transform: translateX(400%);
		}
	}
	.csv-commit-indeterminate-bar {
		animation: csv-commit-indeterminate 1.2s ease-in-out infinite;
	}
</style>
