<script lang="ts">
	import { Button } from '$lib/components/ui/button';
	import * as Dialog from '$lib/components/ui/dialog';
	import { Progress } from '$lib/components/ui/progress';
	import { Loader2, CheckCircle, XCircle, Download } from 'lucide-svelte';
	import {
		expedienteArchivosApi,
		type DigitalizacionResult,
		type DigitalizacionErrorDetail
	} from '$lib/api/dashboard/a76/expediente-archivos';
	import { m } from '$lib/i18n/messages';

	let {
		open = $bindable(false),
		taskId,
		nombreArchivo = '',
		recordId,
		companyId,
		onComplete,
		onCancel
	}: {
		open: boolean;
		taskId: string;
		nombreArchivo?: string;
		recordId?: number;
		companyId?: string | number;
		onComplete?: (result: DigitalizacionResult) => void;
		onCancel?: () => void;
	} = $props();

	type TaskState = 'PENDING' | 'PROGRESS' | 'SUCCESS' | 'FAILURE' | 'STARTED';

	let state = $state<TaskState>('PENDING');
	let currentStep = $state<string>('Iniciando...');
	let progress = $state(0);
	let result = $state<DigitalizacionResult | null>(null);
	let errorMsg = $state<string | null>(null);
	let errorDetail = $state<DigitalizacionErrorDetail | null>(null);
	let externalTaskId = $state<string | null>(null);
	let requestId = $state<string | null>(null);
	let consecutivePollErrors = $state(0);
	let pollHandle: ReturnType<typeof setTimeout> | null = null;
	let pollInFlight = false;
	let pollingActive = false;
	let pollingTaskId: string | null = null;

	// Start / stop polling based on open + taskId
	$effect(() => {
		if (open && taskId) {
			void startPolling();
		} else {
			stopPolling();
			if (!open) resetState();
		}

		return () => stopPolling();
	});

	function resetState() {
		state = 'PENDING';
		currentStep = 'Iniciando...';
		progress = 0;
		result = null;
		errorMsg = null;
		errorDetail = null;
		externalTaskId = null;
		requestId = null;
		consecutivePollErrors = 0;
	}

	async function startPolling() {
		if (pollingActive && pollingTaskId === taskId) return;

		stopPolling();
		pollingActive = true;
		pollingTaskId = taskId;
		await poll();
	}

	function stopPolling() {
		pollingActive = false;
		pollingTaskId = null;
		if (pollHandle !== null) {
			clearTimeout(pollHandle);
			pollHandle = null;
		}
	}

	function scheduleNextPoll(delayMs = 1000) {
		if (!pollingActive || !taskId) return;
		if (pollHandle !== null) {
			clearTimeout(pollHandle);
		}
		pollHandle = setTimeout(() => {
			void poll();
		}, delayMs);
	}

	async function poll() {
		if (!taskId || !pollingActive || pollInFlight) return;
		pollInFlight = true;
		try {
			const res = await expedienteArchivosApi.getStatusTask(taskId);
			if (res.error) {
				consecutivePollErrors += 1;
				if (consecutivePollErrors >= 3 || res.status >= 500) {
					state = 'FAILURE';
					errorMsg = res.error || 'No se pudo consultar el estado de la digitalización';
					errorDetail = {
						codigo: 'TASK_STATUS_REQUEST_ERROR',
						descripcion: res.error || 'El servidor devolvió un error al consultar el estado.',
						paso: 'Consulta de estado',
						sugerencias: ['Cierra el diálogo y vuelve a intentar la digitalización.']
					};
					stopPolling();
				} else {
					scheduleNextPoll();
				}
				return;
			}

			if (!res.data) {
				scheduleNextPoll();
				return;
			}
			const data = res.data;
			consecutivePollErrors = 0;
			externalTaskId = data.external_task_id ?? externalTaskId;
			requestId = data.request_id ?? requestId;

			state = (data.state === 'FAILED' ? 'FAILURE' : data.state || 'PENDING') as TaskState;
			currentStep = data.current_step || 'Procesando...';
			progress = data.progress ?? 0;

			if (data.state === 'SUCCESS') {
				result = data.result ?? null;
				stopPolling();
				onComplete?.(data.result ?? ({} as DigitalizacionResult));
			} else if (data.state === 'FAILURE' || data.state === 'FAILED') {
				errorMsg = data.error || 'Error en la digitalización';
				errorDetail = data.error_detail ?? null;
				stopPolling();
			} else {
				scheduleNextPoll();
			}
		} catch {
			consecutivePollErrors += 1;
			if (consecutivePollErrors >= 3) {
				state = 'FAILURE';
				errorMsg = 'No se pudo consultar el estado de la digitalización';
				errorDetail = {
					codigo: 'TASK_STATUS_NETWORK_ERROR',
					descripcion: 'La consulta de estado falló repetidamente.',
					paso: 'Consulta de estado',
					sugerencias: ['Verifica la conexión y vuelve a intentar la digitalización.']
				};
				stopPolling();
			} else {
				scheduleNextPoll();
			}
		} finally {
			pollInFlight = false;
		}
	}

	async function downloadAcuse() {
		const baseName = (nombreArchivo || taskId).replace(/\.[^.]+$/, '');
		if (recordId != null && companyId != null) {
			try {
				await expedienteArchivosApi.downloadArtifact(
					recordId,
					'acuse',
					companyId,
					`acuse_${baseName}.pdf`
				);
			} catch {
				alert('Error al descargar el acuse.');
			}
		} else if (result?.acuese_digitalizacion_pdf_base64) {
			// fallback: decode base64 locally (registros legacy)
			const bytes = Uint8Array.from(atob(result.acuese_digitalizacion_pdf_base64), (c) =>
				c.charCodeAt(0)
			);
			const blob = new Blob([bytes], { type: 'application/pdf' });
			const url = URL.createObjectURL(blob);
			const a = document.createElement('a');
			a.href = url;
			a.download = `acuse_${baseName}.pdf`;
			document.body.appendChild(a);
			a.click();
			document.body.removeChild(a);
			URL.revokeObjectURL(url);
		}
	}

	function handleCancel() {
		stopPolling();
		open = false;
		onCancel?.();
	}

	const isTerminal = $derived(state === 'SUCCESS' || state === 'FAILURE');
</script>

<Dialog.Root bind:open>
	<Dialog.Content class="max-w-md">
		<Dialog.Header>
			<Dialog.Title>{m['sidebar.digitalizacion.progress_title']()}</Dialog.Title>
			{#if nombreArchivo}
				<Dialog.Description class="truncate">{nombreArchivo}</Dialog.Description>
			{/if}
		</Dialog.Header>

		<div class="space-y-4 py-2">
			{#if state === 'SUCCESS'}
				<!-- Éxito -->
				<div class="flex items-center gap-3 text-green-600">
					<CheckCircle class="h-6 w-6 shrink-0" />
					<p class="text-sm font-medium">{m['sidebar.digitalizacion.progress_success']()}</p>
				</div>
				{#if result}
					<dl class="text-sm space-y-1">
						{#if result.e_document}
							<div class="flex gap-2">
								<dt class="text-muted-foreground min-w-[120px]">E-Document:</dt>
								<dd class="font-medium">{result.e_document}</dd>
							</div>
						{/if}
						{#if result.numero_operacion}
							<div class="flex gap-2">
								<dt class="text-muted-foreground min-w-[120px]">Núm. Operación:</dt>
								<dd class="font-medium">{result.numero_operacion}</dd>
							</div>
						{/if}
					</dl>
				{/if}
				{#if result?.acuese_digitalizacion_pdf_base64 || (recordId != null && companyId != null)}
					<Button onclick={downloadAcuse} class="w-full gap-2">
						<Download class="h-4 w-4" />
						{m['sidebar.digitalizacion.progress_download_acuse']()}
					</Button>
				{/if}

			{:else if state === 'FAILURE'}
				<!-- Error -->
				<div class="flex items-start gap-3 text-destructive">
					<XCircle class="h-6 w-6 shrink-0 mt-0.5" />
					<div class="space-y-1">
						<p class="text-sm font-medium">{errorMsg}</p>
						{#if errorDetail}
							{#if errorDetail.codigo}
								<p class="text-xs text-muted-foreground">Código: {errorDetail.codigo}</p>
							{/if}
							{#if errorDetail.paso}
								<p class="text-xs text-muted-foreground">Paso: {errorDetail.paso}</p>
							{/if}
							{#if errorDetail.sugerencias?.length}
								<ul class="text-xs list-disc pl-4 space-y-0.5 mt-1">
									{#each errorDetail.sugerencias as s}
										<li>{s}</li>
									{/each}
								</ul>
							{/if}
						{/if}
					</div>
				</div>

			{:else}
				<!-- En progreso -->
				<div class="space-y-3">
					<div class="flex items-center gap-3">
						<Loader2 class="h-5 w-5 animate-spin text-primary shrink-0" />
						<p class="text-sm text-muted-foreground">{currentStep}</p>
					</div>
					<Progress value={progress} max={100} class="h-2" />
					<p class="text-xs text-right text-muted-foreground">{progress}%</p>
				</div>
			{/if}

			{#if taskId || externalTaskId || requestId}
				<div class="rounded-md border bg-muted/30 px-3 py-2 space-y-1">
					<p class="text-xs text-muted-foreground">Task App:</p>
					<p class="text-xs font-mono break-all">{taskId}</p>
					{#if externalTaskId}
						<p class="text-xs text-muted-foreground pt-1">Task API:</p>
						<p class="text-xs font-mono break-all">{externalTaskId}</p>
					{/if}
					{#if requestId}
						<p class="text-xs text-muted-foreground pt-1">Request ID:</p>
						<p class="text-xs font-mono break-all">{requestId}</p>
					{/if}
				</div>
			{/if}
		</div>

		<Dialog.Footer class="flex justify-end">
			{#if isTerminal}
				<Button onclick={() => { open = false; }}>Cerrar</Button>
			{:else}
				<Button variant="outline" onclick={handleCancel}>Cancelar</Button>
			{/if}
		</Dialog.Footer>
	</Dialog.Content>
</Dialog.Root>
