<script lang="ts" generics="TData, TValue">
	import {
		type ColumnDef,
		getCoreRowModel
	} from "@tanstack/table-core";
	import { createSvelteTable, FlexRender } from "$lib/components/ui/data-table/index.js";
	import * as Table from "$lib/components/ui/table/index.js";

	type DataTableProps<TData, TValue> = {
		columns: ColumnDef<TData, TValue>[];
		data: TData[];
		loading: boolean;
		selectedIds?: number[];
		onSelectedIdsChange?: (selectedIds: number[]) => void;
		onRowDoubleClick?: (row: TData) => void;
		sorting?: import("@tanstack/table-core").SortingState;
		onSortingChange?: (sorting: import("@tanstack/table-core").SortingState) => void;
	};

	let {
		data,
		columns,
		loading,
		selectedIds = [],
		onSelectedIdsChange,
		onRowDoubleClick,
		sorting = [],
		onSortingChange
	}: DataTableProps<TData, TValue> = $props();

	function getRowIdValue(row: TData): number | null {
		const candidate = (row as { id?: unknown })?.id;
		return typeof candidate === 'number' ? candidate : null;
	}

	function toggleSelectedId(rowId: number, forceSelected?: boolean) {
		const isSelected = selectedIds.includes(rowId);
		const shouldSelect = forceSelected ?? !isSelected;

		if (shouldSelect && !isSelected) {
			onSelectedIdsChange?.([...selectedIds, rowId]);
			return;
		}

		if (!shouldSelect && isSelected) {
			onSelectedIdsChange?.(selectedIds.filter((id) => id !== rowId));
		}
	}

	const table = createSvelteTable({
		get data() {
			return data;
		},
		columns,
		getCoreRowModel: getCoreRowModel(),
		getRowId: (row: any) => row.id?.toString(),
		state: {
			get rowSelection() {
				return Object.fromEntries(selectedIds.map((id) => [id.toString(), true]));
			},
			get sorting() {
				return sorting;
			}
		},
		meta: {
			toggleSelectedId
		},
		onSortingChange: (updater) => {
			if (onSortingChange) {
				const nextSorting = typeof updater === 'function' ? updater(sorting) : updater;
				onSortingChange(nextSorting);
			}
		},
		manualSorting: true,
		enableRowSelection: true,
		enableMultiRowSelection: true
	});
</script>

<div class="w-full h-full flex flex-col overflow-hidden">
	<div class="rounded-md border flex-1 overflow-auto bg-white dark:bg-black">
		<Table.Root class="w-full">
			<Table.Header class="bg-background sticky top-0 z-10">
				{#each table.getHeaderGroups() as headerGroup (headerGroup.id)}
					<Table.Row>
						{#each headerGroup.headers as header (header.id)}
							<Table.Head class="whitespace-nowrap p-0">
								{#if !header.isPlaceholder}
									<button
										class="group flex h-full w-full items-center gap-2 px-2 py-2 text-left hover:bg-muted/50"
										onclick={header.column.getToggleSortingHandler()}
										disabled={!header.column.getCanSort()}
									>
										<FlexRender
											content={header.column.columnDef.header}
											context={header.getContext()}
										/>
										{#if header.column.getCanSort()}
											<div class="flex h-4 w-4 shrink-0 items-center justify-center">
												{#if header.column.getIsSorted() === 'asc'}
													<svg
														xmlns="http://www.w3.org/2000/svg"
														width="14"
														height="14"
														viewBox="0 0 24 24"
														fill="none"
														stroke="currentColor"
														stroke-width="2"
														stroke-linecap="round"
														stroke-linejoin="round"
														class="lucide lucide-chevron-up text-primary"
														><path d="m18 15-6-6-6 6" /></svg
													>
												{:else if header.column.getIsSorted() === 'desc'}
													<svg
														xmlns="http://www.w3.org/2000/svg"
														width="14"
														height="14"
														viewBox="0 0 24 24"
														fill="none"
														stroke="currentColor"
														stroke-width="2"
														stroke-linecap="round"
														stroke-linejoin="round"
														class="lucide lucide-chevron-down text-primary"
														><path d="m6 9 6 6 6-6" /></svg
													>
												{:else}
													<svg
														xmlns="http://www.w3.org/2000/svg"
														width="14"
														height="14"
														viewBox="0 0 24 24"
														fill="none"
														stroke="currentColor"
														stroke-width="2"
														stroke-linecap="round"
														stroke-linejoin="round"
														class="lucide lucide-chevrons-up-down opacity-30 group-hover:opacity-100"
														><path d="m7 15 5 5 5-5" /><path d="m7 9 5-5 5 5" /></svg
													>
												{/if}
											</div>
										{/if}
									</button>
								{/if}
							</Table.Head>
						{/each}
					</Table.Row>
				{/each}
			</Table.Header>
			<Table.Body>
				{#each table.getRowModel().rows as row (row.id)}
					<Table.Row 
						data-state={row.getIsSelected() && "selected"}
						onclick={() => {
							const rowId = getRowIdValue(row.original);
							if (rowId !== null) {
								toggleSelectedId(rowId);
							}
						}}
						ondblclick={() => onRowDoubleClick?.(row.original)}
						class="cursor-pointer hover:bg-muted/50 transition-colors {row.getIsSelected() ? 'bg-primary/10' : ''}"
					>
						{#each row.getVisibleCells() as cell (cell.id)}
							<Table.Cell class="whitespace-nowrap px-2 py-1">
								<FlexRender
									content={cell.column.columnDef.cell}
									context={cell.getContext()}
								/>
							</Table.Cell>
						{/each}
					</Table.Row>
				{:else}
					<Table.Row>
						<Table.Cell colspan={columns.length} class="h-24 text-center">
							{#if loading}
								<div class="flex items-center justify-center gap-2">
									<div class="h-4 w-4 animate-spin rounded-full border-2 border-primary border-t-transparent"></div>
									<p class="text-sm text-muted-foreground">Cargando...</p>
								</div>
							{:else}
								No hay resultados.
							{/if}
						</Table.Cell>
					</Table.Row>
				{/each}
			</Table.Body>
		</Table.Root>
	</div>
</div>
