<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 } from 'lucide-svelte';
	import {
		getDodaAltaStatus,
		type DodaAltaStatusResponse
	} from '$lib/api/dashboard/a76/general_catalogs/doda';
	import type { ApiResponse } from '$lib/api';
	import { m } from '$lib/i18n/messages';

	let {
		open = $bindable(false),
		taskId,
		dodaId,
		variant = 'doda',
		title = m['sidebar.doda_alta.progress_title'](),
		description = 'Task ID',
		getStatus = getDodaAltaStatus,
		onComplete,
		onCancel
	}: {
		open: boolean;
		taskId: string;
		dodaId?: number;
		variant?: 'doda' | 'pita';
		title?: string;
		description?: string;
		getStatus?: (taskId: string) => Promise<ApiResponse<DodaAltaStatusResponse>>;
		onComplete?: (result: DodaAltaStatusResponse) => 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<DodaAltaStatusResponse | null>(null);
	let errorMsg = $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;

	$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;
		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 = 2000) {
		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 getStatus(taskId);

			if (res.error) {
				consecutivePollErrors += 1;
				if (consecutivePollErrors >= 3) {
					state = 'FAILURE';
					errorMsg = res.error || 'No se pudo consultar el estado del alta DODA';
					stopPolling();
				} else {
					scheduleNextPoll();
				}
				return;
			}

			if (!res.data) {
				scheduleNextPoll();
				return;
			}

			const data = res.data;
			consecutivePollErrors = 0;

			const rawState = (data.state || data.status || 'PENDING').toUpperCase();
			state = (rawState === 'FAILED' ? 'FAILURE' : rawState) as TaskState;
			currentStep = (data.message as string) || 'Procesando...';

			if (typeof (data as Record<string, unknown>)['progress'] === 'number') {
				progress = (data as Record<string, unknown>)['progress'] as number;
			}

			if (rawState === 'SUCCESS') {
				result = data;
				stopPolling();
				onComplete?.(data);
			} else if (rawState === 'FAILURE' || rawState === 'FAILED') {
				errorMsg = data.error || data.message || 'Error en el alta DODA';
				stopPolling();
			} else {
				scheduleNextPoll();
			}
		} catch {
			consecutivePollErrors += 1;
			if (consecutivePollErrors >= 3) {
				state = 'FAILURE';
				errorMsg = 'No se pudo consultar el estado del alta DODA';
				stopPolling();
			} else {
				scheduleNextPoll();
			}
		} finally {
			pollInFlight = false;
		}
	}

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

	const isTerminal = $derived(state === 'SUCCESS' || state === 'FAILURE');
	const variantLabel = $derived(variant === 'pita' ? 'PITA' : 'DODA');
</script>

<Dialog.Root bind:open>
	<Dialog.Content class="max-w-md">
		<Dialog.Header>
			<Dialog.Title>{title}</Dialog.Title>
			<Dialog.Description>{description} {variantLabel} — Task ID: {taskId}</Dialog.Description>
		</Dialog.Header>

		<div class="space-y-4 py-2">
			{#if state === 'SUCCESS'}
				<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.doda_alta.progress_success']()}</p>
				</div>
				{#if result}
					<dl class="text-sm space-y-1">
						{#each Object.entries(result) as [key, value]}
							{#if key !== 'state' && value && typeof value === 'string'}
								<div class="flex gap-2">
									<dt class="text-muted-foreground min-w-[130px] capitalize">{key.replace(/_/g, ' ')}:</dt>
									<dd class="font-medium break-all">{value}</dd>
								</div>
							{/if}
						{/each}
					</dl>
				{/if}

			{:else if state === 'FAILURE'}
				<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">{m['sidebar.doda_alta.progress_error']()}</p>
						{#if errorMsg}
							<p class="text-xs text-muted-foreground">{errorMsg}</p>
						{/if}
					</div>
				</div>

			{:else}
				<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>
					{#if progress > 0}
						<Progress value={progress} max={100} class="h-2" />
						<p class="text-xs text-right text-muted-foreground">{progress}%</p>
					{/if}
				</div>
			{/if}

			{#if taskId}
				<div class="rounded-md border bg-muted/30 px-3 py-2">
					<p class="text-xs text-muted-foreground">Task ID:</p>
					<p class="text-xs font-mono break-all">{taskId}</p>
				</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>
