<script lang="ts">
	import * as Dialog from '$lib/components/ui/dialog';
	import { Progress } from '$lib/components/ui/progress';
	import { invoicesReportsApi } from '$lib/api/dashboard/a76/reports/reports-invoices';
	import { toast } from 'svelte-sonner';
	import { Loader2, CheckCircle2, XCircle, FileDown } from 'lucide-svelte';
	import { Button } from '$lib/components/ui/button';

	export let open = false;
	export let taskId: string | null = null;
	export let onClose: () => void;
	export let onComplete: (result: any) => void;
	export let title: string = 'Generando PDF';

	/** Optional: steps for step-by-step progress (e.g. invoice processing). Each step has { label, percent } */
	export let steps: { label: string; percent: number }[] = [];

	/** Optional: message when complete (default: "Listo para descargar") */
	export let completeMessage: string = 'Listo para descargar';

	export let getStatus: ((taskId: string) => Promise<any>) | null = null;

	let progress = 0;
	let statusMessage = 'Iniciando...';
	let pollingInterval: any = null;
	let isComplete = false;
	let hasError = false;

	// Reiniciar estado cuando se abre el diálogo con un nuevo taskId
	$: if (open && taskId) {
		progress = 0;
		statusMessage = 'Iniciando...';
		isComplete = false;
		hasError = false;
		startPolling();
	} else if (!open) {
		stopPolling();
	}

	function stopPolling() {
		if (pollingInterval) {
			clearInterval(pollingInterval);
			pollingInterval = null;
		}
	}

	async function pollOnce() {
			if (!taskId) return;
			const apiCall = getStatus || invoicesReportsApi.getTaskStatus;
			const raw = await apiCall(taskId);
			const response = raw?.data !== undefined ? raw.data : raw;
			if (raw?.error) {
				hasError = true;
				statusMessage = `Error: ${raw.error}`;
				stopPolling();
				toast.error(raw.error);
				return;
			}
			if (response?.state === 'PROCESSING' && response.info) {
				progress = response.info.current || 0;
				statusMessage = response.info.status || 'Procesando...';
			} else if (response?.state === 'SUCCESS') {
				const result = response.result;
				stopPolling();

				// Si el worker reportó error de validación o error de aplicación,
				// cerrar el dialog inmediatamente y dejar que onComplete muestre el toast.
				if (result?.status === 'validation_error' || result?.status === 'error') {
					open = false;
					onComplete(result);
				} else {
					progress = 100;
					statusMessage = '¡Completado!';
					isComplete = true;
					setTimeout(() => onComplete(result), 500);
				}
			} else if (response?.state === 'FAILURE') {
				hasError = true;
				const errMsg = response.result ? String(response.result) : 'Error desconocido';
				statusMessage = `Error: ${errMsg}`;
				stopPolling();
				toast.error(`Falló: ${errMsg}`);
			}
		}

	async function startPolling() {
		stopPolling(); // Asegurar limpieza previa
		await pollOnce(); // Primer poll inmediato para mostrar progreso sin esperar 1s

		pollingInterval = setInterval(async () => {
			if (isComplete || hasError) return;
			try {
				await pollOnce();
			} catch (error) {
				console.error('Error polling task status:', error);
			}
		}, 1000);
	}

	function handleOpenChange(newOpen: boolean) {
		if (!newOpen) {
			stopPolling();
			onClose();
		}
	}
</script>

<Dialog.Root bind:open onOpenChange={handleOpenChange}>
	<Dialog.Content class="sm:max-w-[425px]">
		<Dialog.Header>
			<Dialog.Title>{title}</Dialog.Title>
			<Dialog.Description>Por favor espere mientras se genera su documento.</Dialog.Description>
		</Dialog.Header>

		<div class="flex flex-col gap-6 py-6">
			{#if steps.length > 0}
				<!-- Lista de pasos con progreso -->
				<div class="space-y-2">
					{#each steps as step, i}
						{@const isDone = progress >= step.percent}
						{@const isCurrent = !isDone && (i === 0 || progress >= steps[i - 1]?.percent)}
						<div
							class="flex items-center gap-3 rounded-md border px-3 py-2 text-sm transition-colors {isDone
								? 'border-green-200 bg-green-50 dark:border-green-900 dark:bg-green-950/30'
								: isCurrent
									? 'border-primary/50 bg-primary/5'
									: 'border-border/50 bg-muted/30 opacity-60'}"
						>
							<span class="flex-shrink-0 w-6 text-center font-medium text-muted-foreground">
								{i + 1}.
							</span>
							<span class="flex-1 {isDone ? 'text-green-700 dark:text-green-400' : ''}">
								{step.label}
							</span>
							<span class="flex-shrink-0 font-medium tabular-nums">
								{#if isDone}
									<span class="text-green-600 dark:text-green-400">100%</span>
								{:else if isCurrent}
									<span class="text-primary">{progress}%</span>
								{:else}
									<span class="text-muted-foreground">0%</span>
								{/if}
							</span>
							{#if isDone}
								<CheckCircle2 class="h-4 w-4 flex-shrink-0 text-green-600" />
							{:else if isCurrent}
								<Loader2 class="h-4 w-4 flex-shrink-0 animate-spin text-primary" />
							{/if}
						</div>
					{/each}
				</div>
				<Progress value={progress} class="h-1.5 w-full" />
			{:else}
				<div class="mb-1 flex items-center justify-between text-sm">
					<span class="text-muted-foreground">{statusMessage}</span>
					<span class="font-medium">{progress}%</span>
				</div>
				<Progress value={progress} class="h-2 w-full" />
			{/if}

			<div class="flex h-16 items-center justify-center">
				{#if isComplete}
					<div
						class="animate-in fade-in zoom-in flex flex-col items-center text-green-600 duration-300"
					>
						<CheckCircle2 size={48} />
						<span class="mt-2 text-sm font-medium">{completeMessage}</span>
					</div>
				{:else if hasError}
					<div
						class="animate-in fade-in zoom-in flex flex-col items-center text-destructive duration-300"
					>
						<XCircle size={48} />
						<span class="mt-2 text-sm font-medium">Ocurrió un error</span>
					</div>
				{:else}
					<div class="flex animate-pulse flex-col items-center text-primary">
						<FileDown size={48} class="opacity-50" />
					</div>
				{/if}
			</div>
		</div>

		<Dialog.Footer>
			{#if hasError}
				<Button variant="secondary" onclick={onClose}>Cerrar</Button>
			{/if}
		</Dialog.Footer>
	</Dialog.Content>
</Dialog.Root>
