<script lang="ts">
	import { Button } from '$lib/components/ui/button';
	import { Input } from '$lib/components/ui/input';
	import * as Dialog from '$lib/components/ui/dialog';
	import * as Table from '$lib/components/ui/table';
	import { Search, Loader2, MapPin } from 'lucide-svelte';
	import { statesApi, type State } from '$lib/api/dashboard/reference_data/states';
	import { companyStore } from '$lib/stores/company.svelte';
	import { toast } from 'svelte-sonner';

	// --- PROPS ---
	let {
		open = $bindable(false),
		onSelect,
		onClear
	}: {
		open: boolean;
		onSelect: (item: State) => void;
		onClear?: () => void;
	} = $props();

	// --- ESTADO ---
	let items = $state<State[]>([]);
	let loading = $state(false);
	let loadingMore = $state(false);
	let searchTerm = $state('');
	let previousSearchTerm = '';
	let page = $state(1);
	let pageSize = 50;
	let hasMore = $state(true);
	let totalItems = $state(0);
	let observer: IntersectionObserver | null = null;
	let bottomSentinel: HTMLElement | null = $state(null);
	let searchTimeout: any;
	let isInitialized = false;

	// Cargar datos iniciales al abrir
	$effect(() => {
		if (open && !isInitialized) {
			isInitialized = true;
			previousSearchTerm = searchTerm;
			resetAndLoad();
		} else if (!open) {
			isInitialized = false;
		}
	});

	// Manejar búsqueda con debouncing
	$effect(() => {
		const term = searchTerm;
		if (isInitialized && term !== previousSearchTerm) {
			if (searchTimeout) clearTimeout(searchTimeout);
			searchTimeout = setTimeout(() => {
				previousSearchTerm = term;
				resetAndLoad();
			}, 500);
		}
	});

	// Configurar IntersectionObserver para infinite scroll
	$effect(() => {
		if (bottomSentinel && hasMore && !loading && !loadingMore && open) {
			if (observer) observer.disconnect();

			observer = new IntersectionObserver(
				(entries) => {
					if (entries[0].isIntersecting && hasMore && !loading && !loadingMore) {
						loadMore();
					}
				},
				{ threshold: 0.1 }
			);

			observer.observe(bottomSentinel);
		}

		return () => {
			if (observer) observer.disconnect();
		};
	});

	async function resetAndLoad() {
		page = 1;
		items = [];
		hasMore = true;
		await loadStates(true);
	}

	async function loadMore() {
		if (!hasMore || loading || loadingMore) return;
		page += 1;
		await loadStates(false);
	}

	async function loadStates(isInitial: boolean) {
		if (isInitial) {
			loading = true;
		} else {
			loadingMore = true;
		}

		try {
			// Note: statesApi.list takes page, pageSize, and searchTerm?
			// Wait, let me check statesApi.list signature again.
			// It only takes page and pageSize! I need to check if it supports search.
			const companyId = companyStore.activeCompany?.id || 1;
			const response = await statesApi.list(companyId, page, pageSize);

			if (response.error) {
				toast.error(`Error: ${response.error}`);
				hasMore = false;
				return;
			}

			// Local filtering if search term exists (temporary workaround if API doesn't support it)
			let newItems = response.data?.items || [];
			totalItems = response.data?.total || 0;

			if (searchTerm) {
				newItems = newItems.filter(
					(item) =>
						item.description.toLowerCase().includes(searchTerm.toLowerCase()) ||
						item.m3_key.toLowerCase().includes(searchTerm.toLowerCase())
				);
			}

			if (isInitial) {
				items = newItems;
			} else {
				items = [...items, ...newItems];
			}

			hasMore = items.length < totalItems && newItems.length > 0;
		} catch (e: any) {
			console.error('Error loading states:', e);
			toast.error('Error al conectar con el servidor');
			hasMore = false;
		} finally {
			loading = false;
			loadingMore = false;
		}
	}

	function handleSelect(item: State) {
		if (onSelect) onSelect(item);
		open = false;
	}
</script>

<Dialog.Root bind:open>
	<Dialog.Content class="flex max-h-[90vh] flex-col sm:max-w-[800px]">
		<Dialog.Header>
			<Dialog.Title>Seleccionar Estado</Dialog.Title>
			<Dialog.Description>
				Seleccione el estado del catálogo. Escrolea para ver más.
			</Dialog.Description>
		</Dialog.Header>

		<div class="relative my-2 w-full">
			<Search class="absolute top-2.5 left-2.5 h-4 w-4 text-muted-foreground" />
			<Input
				type="search"
				placeholder="Filtrar por clave o descripción..."
				class="pl-9"
				bind:value={searchTerm}
			/>
		</div>

		<div class="min-h-[300px] flex-1 overflow-y-auto rounded-md border">
			{#if loading && items.length === 0}
				<div class="flex h-48 flex-col items-center justify-center gap-2 text-muted-foreground">
					<Loader2 class="h-8 w-8 animate-spin text-primary" />
					<p>Cargando catálogo...</p>
				</div>
			{:else if items.length === 0}
				<div class="flex h-48 flex-col items-center justify-center text-muted-foreground">
					<p>No se encontraron estados.</p>
				</div>
			{:else}
				<Table.Root>
					<Table.Header>
						<Table.Row>
							<Table.Head class="w-[100px]">Clave M3</Table.Head>
							<Table.Head>Descripción</Table.Head>
							<Table.Head class="w-[80px]">MEX</Table.Head>
						</Table.Row>
					</Table.Header>
					<Table.Body>
						{#each items as item}
							<Table.Row
								class="cursor-pointer transition-colors hover:bg-accent/50"
								onclick={() => handleSelect(item)}
							>
								<Table.Cell>
									<div class="flex items-center gap-1">
										<MapPin class="h-3 w-3 text-red-500" />
										<span class="font-mono text-xs font-bold">
											{item.m3_key}
										</span>
									</div>
								</Table.Cell>
								<Table.Cell class="text-sm font-medium">
									{item.description}
								</Table.Cell>
								<Table.Cell class="font-mono text-xs">
									{item.mex_key || '-'}
								</Table.Cell>
							</Table.Row>
						{/each}
					</Table.Body>
				</Table.Root>

				<div bind:this={bottomSentinel} class="flex h-10 items-center justify-center">
					{#if loadingMore}
						<Loader2 class="h-5 w-5 animate-spin text-muted-foreground" />
					{/if}
				</div>
			{/if}
		</div>

		<Dialog.Footer>
			<div class="mr-auto self-center text-xs text-muted-foreground">
				{items.length} de {totalItems} registros
			</div>
			{#if onClear}
				<Button variant="ghost" onclick={() => { onClear(); open = false; }}>Quitar selección</Button>
			{/if}
			<Button variant="outline" onclick={() => (open = false)}>Cancelar</Button>
		</Dialog.Footer>
	</Dialog.Content>
</Dialog.Root>
