<script lang="ts">
	import { page } from '$app/stores';
	import { goto } from '$app/navigation';
        import { browser } from '$app/environment';
        import { toast } from 'svelte-sonner';
		import { m } from '$lib/i18n/messages';
        import * as Card from '$lib/components/ui/card';
        import { Button } from '$lib/components/ui/button';
        import { Input } from '$lib/components/ui/input';
        import { Label } from '$lib/components/ui/label';
        import * as Select from '$lib/components/ui/select';
        import { Plus, RefreshCw, FileCheck2, Download, FolderArchive, Pencil, Trash2, Filter } from 'lucide-svelte';

        import InfiniteDataTable from '$lib/components/dashboard/common/infinite-data-table.svelte';
        import CreateEditDialog from '$lib/components/dashboard/digitalizacion/create-edit-dialog.svelte';
        import ProgressDialog from '$lib/components/dashboard/digitalizacion/progress-dialog.svelte';
        import { createColumns } from '$lib/components/dashboard/digitalizacion/columns';

        import {
                expedienteArchivosApi,
                type ExpedienteArchivo,
                type DigitalizacionResult
        } from '$lib/api/dashboard/a76/expediente-archivos';
        import { companyStore } from '$lib/stores/company.svelte';
        import { useShortcuts } from '$lib/hooks/use-shortcuts';
        import { obtenerAtajosDigitalizacion } from '$lib/config/shortcuts/dashboard/a76/digitalizacion/list';
	// ── Estado ─────────────────────────────────────────────────────────────── //
	let data = $state<ExpedienteArchivo[]>([]);
	let totalItems = $state(0);
	let loading = $state(false);
	let currentPage = $state(1);
	let pageSize = $state(50);
	let hasMore = $derived(data.length < totalItems);

	let search = $state($page.url.searchParams.get('search') || '');
	let searchEDocument = $state('');
	let searchRFC = $state('');
	let searchStatus = $state('all');
	let showFilters = $state(false);
	let searchTimeout: ReturnType<typeof setTimeout>;

	// Selección de filas
	let selectedIds = $state<number[]>([]);
	const selectedItems = $derived(data.filter((item) => selectedIds.includes(item.id)));
	const selectedItem = $derived(selectedItems.length === 1 ? selectedItems[0] : null);
const canOpenAcuse = $derived(selectedItem?.status === 'success' && !!selectedItem?.acuse_pdf_path);
        const canDownloadEnvioXml = $derived(!!selectedItem?.envio_xml_path);
        const canDownloadRespuestaXml = $derived(!!selectedItem?.respuesta_xml_path);
        const canDownloadConsultaEnvioXml = $derived(!!selectedItem?.consulta_envio_xml_path);
        const canDownloadConsultaRespuestaXml = $derived(!!selectedItem?.consulta_respuesta_xml_path);
        const canDownloadZip = $derived(selectedItem?.status === 'success');

	// Dialogs
	let createDialogOpen = $state(false);
	let editDialogOpen = $state(false);
	let progressDialogOpen = $state(false);
	let editingItem = $state<ExpedienteArchivo | null>(null);
	let digitalizarItem = $state<ExpedienteArchivo | null>(null);
	let currentTaskId = $state<string>('');
	let currentNombreArchivo = $state<string>('');



	// ── Carga de datos ─────────────────────────────────────────────────────── //
	async function loadData() {
		if (!companyStore.activeCompany) return;
		loading = true;
		try {
			const res = await expedienteArchivosApi.list(companyStore.activeCompany.id, {
				page: 1,
				page_size: pageSize,
				search: search || undefined,
				e_document: searchEDocument || undefined,
				rfc_consulta: searchRFC || undefined,
				status: searchStatus === 'all' ? undefined : searchStatus
			});
			if (res.data) {
				data = res.data.items;
				currentPage = 1;
				totalItems = res.data.total;
				selectedIds = selectedIds.filter((id) => data.some((item) => item.id === id));
			}
		} catch (e) {
			console.error('Error loading expediente archivos:', e);
		} finally {
			loading = false;
		}
	}

	async function loadMore() {
		if (loading || !hasMore || !companyStore.activeCompany) return;
		loading = true;
		try {
			const res = await expedienteArchivosApi.list(companyStore.activeCompany.id, {
				page: currentPage + 1,
				page_size: pageSize,
				search: search || undefined,
				e_document: searchEDocument || undefined,
				rfc_consulta: searchRFC || undefined,
				status: searchStatus === 'all' ? undefined : searchStatus
			});
			if (res.data?.items) {
				data = [...data, ...res.data.items];
				currentPage += 1;
				totalItems = res.data.total;
			}
		} catch (e) {
			console.error('Error loading more:', e);
		} finally {
			loading = false;
		}
	}

	function handleSearch() {
		if (!browser) return;
		clearTimeout(searchTimeout);
		searchTimeout = setTimeout(() => {
			const url = new URL($page.url);
			if (search) url.searchParams.set('search', search);
			else url.searchParams.delete('search');
			goto(url, { keepFocus: true, noScroll: true });
		}, 500);
	}

	$effect(() => {
		const _ = { p: $page.url.href, c: companyStore.activeCompany?.id };
		loadData();
	});

	// ── Handlers de acciones ───────────────────────────────────────────────── //
	function handleRowClick(item: ExpedienteArchivo) {
		if (selectedIds.includes(item.id)) {
			selectedIds = selectedIds.filter((id) => id !== item.id);
			return;
		}

		selectedIds = [...selectedIds, item.id];
	}

	function handleSelectedIdsChange(ids: (string | number)[]) {
		selectedIds = ids.map((id) => (typeof id === 'number' ? id : Number(id)));
	}

	async function handleDigitalizar(item: ExpedienteArchivo) {
		const company = companyStore.activeCompany;
		if (!company) {
			alert('No hay compañía seleccionada.');
			return;
		}
		if (!item.tipo_documento?.trim()) {
			alert('El documento no tiene Clave Documento capturada.');
			return;
		}
		if (!item.nombre_archivo?.trim() || !item.archivo_digitalizado_en?.trim()) {
			alert('El documento no tiene archivo cargado. Edita el registro y vuelve a seleccionar el archivo.');
			return;
		}

		digitalizarItem = item;

		const response = await expedienteArchivosApi.digitalizar(
			item.id,
			{
				rfc_consulta: item.rfc_consulta?.trim() || undefined,
				clave_documento: item.tipo_documento.trim(),
				nombre_archivo: item.nombre_archivo.trim(),
				archivo_base64: undefined
			},
			company.id
		);

		if (response.error) {
			const ve = (response as any).validationErrors;
			if (ve?.length) {
				alert(ve.map((error: any) => error.msg).join(' · '));
				return;
			}
			alert(response.error);
			return;
		}

		const taskId = response.data?.task_id;
		if (!taskId) {
			alert('No se recibió task_id del servidor');
			return;
		}

		handleDigitalizarSuccess(taskId);
	}

	async function handleDigitalizarSelected() {
		if (!selectedItem) {
			alert('Selecciona un documento para digitalizar.');
			return;
		}

		await handleDigitalizar(selectedItem);
	}

	function handleDigitalizarSuccess(taskId: string) {
		currentTaskId = taskId;
		currentNombreArchivo = digitalizarItem?.nombre_archivo ?? '';
		progressDialogOpen = true;
	}

	function handleProgressComplete(_result: DigitalizacionResult) {
		loadData();
	}

async function handleDownloadArtifact(
                item: ExpedienteArchivo,
                type: 'acuse' | 'envio-xml' | 'respuesta-xml' | 'consulta-envio-xml' | 'consulta-respuesta-xml',
                filename: string
        ) {
                if (!companyStore.activeCompany) return;
                try {
                        await expedienteArchivosApi.downloadArtifact(item.id, type, companyStore.activeCompany.id, filename);
                } catch {
                        alert('Error al descargar el archivo.');
                }
        }

        async function handleAcuse(item: ExpedienteArchivo) {
                const baseName = (item.nombre_archivo || String(item.id)).replace(/\.[^.]+$/, '');
                await handleDownloadArtifact(item, 'acuse', `acuse_${baseName}.pdf`);
        }

        function handleAcuseSelected() {
                if (!selectedItem) {
                        alert('Selecciona un documento para descargar el acuse.');
                        return;
                }
                handleAcuse(selectedItem);
        }

        function handleDownloadSelected(
                type: 'envio-xml' | 'respuesta-xml' | 'consulta-envio-xml' | 'consulta-respuesta-xml',
                prefix: string,
                ext: string
        ) {
                if (!selectedItem) return;
                const baseName = (selectedItem.nombre_archivo || String(selectedItem.id)).replace(/\.[^.]+$/, '');
                handleDownloadArtifact(selectedItem, type, `${prefix}_${baseName}.${ext}`);
	}

        async function handleDownloadZip() {
                if (!selectedItem || !companyStore.activeCompany) return;
                try {
                        await expedienteArchivosApi.downloadAllArtifactsZip(
                                selectedItem.id,
                                companyStore.activeCompany.id,
                                selectedItem.e_document || String(selectedItem.id)
                        );
                } catch {
                        alert('Error al descargar el ZIP.');
                }
        }

	function handleEditSelected() {
		if (!selectedItem) {
			alert('Selecciona un documento para editar.');
			return;
		}

		editingItem = selectedItem;
		editDialogOpen = true;
	}

	async function handleFooterDelete() {
		if (!companyStore.activeCompany || selectedIds.length === 0) return;

		const confirmed =
			selectedIds.length === 1
				? confirm(m['sidebar.digitalizacion.confirm_delete']())
				: confirm(`Se eliminarán ${selectedIds.length} documentos digitalizados. ¿Deseas continuar?`);

		if (!confirmed) return;

		try {
			const results = await Promise.all(
				selectedIds.map((id) => expedienteArchivosApi.delete(id, companyStore.activeCompany!.id))
			);
			const firstError = results.find((result) => result.error)?.error;

			if (firstError) {
				alert(`Error al eliminar: ${firstError}`);
				return;
			}

			selectedIds = [];
			await loadData();
		} catch (e) {
			alert(`Error: ${e instanceof Error ? e.message : 'Error desconocido'}`);
		}
	}

	const columns = createColumns(loadData, handleDigitalizar, handleAcuse);

        // ── Navegación por teclado ─────────────────────────────────────────────── //

        function focusFirstTableRow() {
                if (!browser) return;
                const row = document.querySelector<HTMLElement>(
                        '[data-digitalizacion-list-table] tbody tr[data-slot="table-row"]'
                );
                if (row) {
                        row.focus();
                        setTimeout(() => row.scrollIntoView({ behavior: 'smooth', block: 'nearest' }), 50);
                        return;
                }
                toast.info('No hay filas en la tabla');
        }

        function focusFooterActions() {
                if (!browser) return;
                const footer = document.getElementById('digitalizacion-list-footer');
                if (!footer) return;
                const candidates = footer.querySelectorAll<HTMLElement>(
                        'button:not([disabled]), a[href], [tabindex]:not([tabindex="-1"])'
                );
                for (const el of candidates) {
                        if (el.offsetParent === null && el.getClientRects().length === 0) continue;
                        el.focus();
                        setTimeout(() => el.scrollIntoView({ behavior: 'smooth', block: 'nearest' }), 50);
                        return;
                }
        }

        function getFooterToolbarButtons(): HTMLButtonElement[] {
                const toolbar = document.querySelector('#digitalizacion-list-footer [data-digitalizacion-footer-toolbar]');
                if (!toolbar) return [];
                return Array.from(toolbar.querySelectorAll<HTMLButtonElement>('[data-footer-action]'));
        }

        function handleFooterToolbarKeydown(event: KeyboardEvent) {
                if (event.key !== 'ArrowLeft' && event.key !== 'ArrowRight') return;
                const target = event.target as HTMLElement | null;
                if (!target?.closest('[data-digitalizacion-footer-toolbar]')) return;
                if (target.closest('[data-slot="dropdown-menu-content"]')) return;

                const buttons = getFooterToolbarButtons().filter((b) => !b.disabled);
                if (buttons.length === 0) return;
                const active = document.activeElement as HTMLButtonElement | null;
                let idx = active ? buttons.indexOf(active) : -1;
                if (idx === -1) {
                        idx = event.key === 'ArrowRight' ? 0 : buttons.length - 1;
                } else if (event.key === 'ArrowRight') {
                        idx = (idx + 1) % buttons.length;
                } else {
                        idx = (idx - 1 + buttons.length) % buttons.length;
                }
                event.preventDefault();
                buttons[idx]?.focus();
        }

        useShortcuts(
                'Digitalizacion List',
                obtenerAtajosDigitalizacion({
                        manejarNuevo: () => (createDialogOpen = true),
                        manejarActualizar: loadData,
                        manejarDigitalizar: handleDigitalizarSelected,
                        manejarEditar: handleEditSelected,
                        manejarEliminar: () => {
                                if (selectedIds.length === 0) {
                                        toast.info('Selecciona al menos un documento para eliminar');
                                        return;
                                }
                                handleFooterDelete();
                        },
                        manejarDescargarZip: () => {
                                if (!selectedItem || !canDownloadZip) {
                                        toast.info('Selecciona un documento digitalizado para descargar ZIP');
                                        return;
                                }
                                handleDownloadZip();
                        },
                        irATabla: focusFirstTableRow,
                        irAAcciones: focusFooterActions,
                })
        );
</script>

<div
	class="flex flex-col gap-6 p-6 h-[calc(100svh-4rem)] group-has-data-[collapsible=icon]/sidebar-wrapper:h-[calc(100svh-3rem)] overflow-hidden pb-[5.5rem]"
>
	<!-- Header -->
	<div class="flex items-center justify-between">
		<div>
			<h1 class="text-2xl font-bold tracking-tight">
				{m['sidebar.digitalizacion.title']()}
			</h1>
			<p class="text-muted-foreground">{m['sidebar.digitalizacion.subtitle']()}</p>
		</div>
		<div class="flex items-center gap-3">
			<Button variant="outline" size="sm" class="h-9" onclick={loadData}>
				<RefreshCw class="mr-2 h-4 w-4" />
				{m['sidebar.digitalizacion.refresh']()}
			</Button>
		</div>
	</div>

	<!-- Table card -->
	<Card.Root class="border bg-background flex flex-col flex-1 min-h-0">
		<Card.Header>
			<div class="flex flex-wrap items-center justify-between gap-3">
				<Card.Title>{m['sidebar.digitalizacion.table_title']()}</Card.Title>
				<div class="flex items-center gap-2">
					<Button
						variant={showFilters ? 'secondary' : 'outline'}
						size="sm"
						class="h-9"
						onclick={() => (showFilters = !showFilters)}
					>
						<Filter class="mr-2 h-4 w-4" />
						Filtros
					</Button>
					<Input
						placeholder="{m['sidebar.digitalizacion.search_placeholder']()} ..."
						class="h-9 w-56 bg-card"
						bind:value={search}
						oninput={handleSearch}
					/>
				</div>
			</div>

			{#if showFilters}
				<div class="mt-4 grid grid-cols-1 gap-4 rounded-lg border bg-muted/30 p-4 sm:grid-cols-2 md:grid-cols-4">
					<!-- E-Document -->
					<div class="space-y-2">
						<Label class="text-xs font-medium uppercase tracking-wider text-muted-foreground">E-Document</Label>
						<Input
							placeholder="Buscar por E-Document..."
							class="h-8 bg-background text-sm"
							bind:value={searchEDocument}
							oninput={handleSearch}
						/>
					</div>

					<!-- RFC -->
					<div class="space-y-2">
						<Label class="text-xs font-medium uppercase tracking-wider text-muted-foreground">RFC Consulta</Label>
						<Input
							placeholder="Buscar por RFC..."
							class="h-8 bg-background text-sm"
							bind:value={searchRFC}
							oninput={handleSearch}
						/>
					</div>

					<!-- Status -->
					<div class="space-y-2">
						<Label class="text-xs font-medium uppercase tracking-wider text-muted-foreground">Estatus</Label>
						<Select.Root
							type="single"
							value={searchStatus}
							onValueChange={(v) => {
								searchStatus = v || 'all';
								loadData();
							}}
						>
							<Select.Trigger class="h-8 bg-background text-sm">
								<Select.Value placeholder="Todos los estatus" />
							</Select.Trigger>
							<Select.Content>
								<Select.Item value="all">Todos</Select.Item>
								<Select.Item value="pending">Pendiente</Select.Item>
								<Select.Item value="processing">Procesando</Select.Item>
								<Select.Item value="success">Completado</Select.Item>
								<Select.Item value="failed">Fallido</Select.Item>
							</Select.Content>
						</Select.Root>
					</div>

					<!-- Limpiar -->
					<div class="flex items-end">
						<Button
							variant="ghost"
							size="sm"
							class="h-8 w-full text-xs"
							onclick={() => {
								searchEDocument = '';
								searchRFC = '';
								searchStatus = 'all';
								search = '';
								loadData();
							}}
						>
							Limpiar filtros
						</Button>
					</div>
				</div>
			{/if}
		</Card.Header>
		<Card.Content class="p-0 flex-1 min-h-0 overflow-hidden">
			{#if loading && data.length === 0}
				<div class="flex h-64 items-center justify-center text-muted-foreground">
					{m['sidebar.digitalizacion.loading']()}
				</div>
			{:else if data.length === 0 && !loading}
				<div class="flex h-64 items-center justify-center text-muted-foreground">
					{m['sidebar.digitalizacion.empty']()}
				</div>
			{:else}
				<div class="rounded-md border bg-background overflow-hidden h-full" data-digitalizacion-list-table>
					<InfiniteDataTable
						{data}
						{columns}
						{loading}
						{hasMore}
						{loadMore}
						{selectedIds}
						onSelectedIdsChange={handleSelectedIdsChange}
						onRowClick={handleRowClick}
					/>
				</div>
			{/if}
		</Card.Content>
	</Card.Root>

	<div class="flex-none text-sm text-muted-foreground">
		Mostrando {data.length} de {totalItems} registros
	</div>
</div>

<!-- Footer fijo con botones de acción -->
<div
	id="digitalizacion-list-footer"
	class="fixed right-0 bottom-0 left-0 z-[5] ml-[calc(var(--sidebar-width))] border-t bg-background/95 shadow-lg backdrop-blur group-has-data-[state=collapsed]/sidebar-wrapper:ml-[calc(var(--sidebar-width-icon))] supports-[backdrop-filter]:bg-background/80"
>
	<div class="mx-auto max-w-[1400px] px-4 py-4">
		<div
			role="toolbar"
			tabindex="0"
			aria-label="Acciones de digitalización"
			data-digitalizacion-footer-toolbar
			class="flex w-full items-center justify-end gap-2"
			onkeydown={handleFooterToolbarKeydown}
		>
			<Button variant="outline" size="sm" data-footer-action="nuevo" onclick={() => (createDialogOpen = true)}>
				<Plus class="mr-2 h-4 w-4" />
				{m['sidebar.digitalizacion.new']()}
			</Button>

			<div class="h-6 w-px bg-border"></div>

			<Button
				variant="outline"
				size="sm"
				data-footer-action="digitalizar"
				disabled={selectedIds.length !== 1}
				onclick={handleDigitalizarSelected}
			>
				<FileCheck2 class="mr-2 h-4 w-4" />
				{m['sidebar.digitalizacion.action_digitalizar']()}
			</Button>

			<Button
				variant="outline"
				size="sm"
				data-footer-action="acuse"
				disabled={selectedIds.length !== 1 || !canOpenAcuse}
				onclick={handleAcuseSelected}
			>
				<Download class="mr-2 h-4 w-4" />
				{m['sidebar.digitalizacion.action_acuse']()}
			</Button>

			<Button
				variant="outline"
				size="sm"
				data-footer-action="envio-xml"
				disabled={selectedIds.length !== 1 || !canDownloadEnvioXml}
				onclick={() => handleDownloadSelected('envio-xml', 'envio', 'xml')}
			>
				<Download class="mr-2 h-4 w-4" />
				{m['sidebar.digitalizacion.action_envio_xml']()}
			</Button>

			<Button
				variant="outline"
				size="sm"
				data-footer-action="respuesta-xml"
				disabled={selectedIds.length !== 1 || !canDownloadRespuestaXml}
				onclick={() => handleDownloadSelected('respuesta-xml', 'respuesta', 'xml')}
			>
				<Download class="mr-2 h-4 w-4" />
				{m['sidebar.digitalizacion.action_respuesta_xml']()}
			</Button>

			<Button
				variant="outline"
				size="sm"
				data-footer-action="consulta-envio-xml"
				disabled={selectedIds.length !== 1 || !canDownloadConsultaEnvioXml}
				onclick={() => handleDownloadSelected('consulta-envio-xml', 'consulta_envio', 'xml')}
			>
				<Download class="mr-2 h-4 w-4" />
				{m['sidebar.digitalizacion.action_consulta_envio_xml']()}
			</Button>

			<Button
				variant="outline"
				size="sm"
				data-footer-action="consulta-respuesta-xml"
				disabled={selectedIds.length !== 1 || !canDownloadConsultaRespuestaXml}
				onclick={() => handleDownloadSelected('consulta-respuesta-xml', 'consulta_respuesta', 'xml')}
			>
				<Download class="mr-2 h-4 w-4" />
				{m['sidebar.digitalizacion.action_consulta_respuesta_xml']()}
			</Button>

			<Button
				variant="outline"
				size="sm"
				data-footer-action="zip"
				disabled={selectedIds.length !== 1 || !canDownloadZip}
				onclick={handleDownloadZip}
			>
				<FolderArchive class="mr-2 h-4 w-4" />
				{m['sidebar.digitalizacion.action_download_zip']()}
			</Button>

			<Button
				variant="outline"
				size="sm"
				data-footer-action="editar"
				disabled={selectedIds.length !== 1}
				onclick={handleEditSelected}
			>
				<Pencil class="mr-2 h-4 w-4" />
				{m['sidebar.digitalizacion.action_edit']()}
			</Button>

			<Button
				variant="outline"
				size="sm"
				data-footer-action="eliminar"
				disabled={selectedIds.length === 0}
				onclick={handleFooterDelete}
			>
				<Trash2 class="mr-2 h-4 w-4" />
				{m['sidebar.digitalizacion.action_delete']()}
			</Button>
		</div>
	</div>
</div>

<!-- Dialogs -->
<CreateEditDialog bind:open={createDialogOpen} onSuccess={loadData} />

{#if editingItem}
	<CreateEditDialog bind:open={editDialogOpen} item={editingItem} onSuccess={loadData} />
{/if}

{#if progressDialogOpen && currentTaskId}
	<ProgressDialog
		bind:open={progressDialogOpen}
		taskId={currentTaskId}
		nombreArchivo={currentNombreArchivo}
		recordId={digitalizarItem?.id}
		companyId={companyStore.activeCompany?.id}
		onComplete={handleProgressComplete}
		onCancel={() => { progressDialogOpen = false; loadData(); }}
	/>
{/if}
