<script lang="ts" generics="T extends Record<string, any>">
	import { 
		createSvelteTable,
		getCoreRowModel,
		getSortedRowModel,
		type ColumnDef,
		type SortingState,
		type TableOptions
	} from 'tanstack-table-8-svelte-5';
	import { writable } from 'svelte/store';
	import EmptyState from './EmptyState.svelte';
	import LoadingState from './LoadingState.svelte';
	import { ChevronUp, ChevronDown, ChevronsUpDown } from 'lucide-svelte';

	interface Props {
		data: T[];
		columns: ColumnDef<T>[];
		loading?: boolean;
		emptyTitle?: string;
		emptyDescription?: string;
		onRowClick?: (row: T) => void;
	}

	let { 
		data, 
		columns, 
		loading = false,
		emptyTitle = 'No data',
		emptyDescription = 'No records found.',
		onRowClick
	}: Props = $props();

	const sorting = writable<SortingState>([]);
	
	const options: TableOptions<T> = $derived({
		get data() { return data; },
		get columns() { return columns; },
		state: {
			get sorting() {
				return $sorting;
			}
		},
		onSortingChange: (updater) => {
			if (typeof updater === 'function') {
				sorting.update(updater);
			} else {
				sorting.set(updater);
			}
		},
		getCoreRowModel: getCoreRowModel(),
		getSortedRowModel: getSortedRowModel()
	});

	const table = createSvelteTable(options);
	
	let rows = $derived($table.getRowModel().rows);
	let isEmpty = $derived(!loading && rows.length === 0);
	let headerGroups = $derived($table.getHeaderGroups());

	function getSortIcon(columnId: string) {
		const sort = $sorting.find(s => s.id === columnId);
		if (!sort) return ChevronsUpDown;
		return sort.desc ? ChevronDown : ChevronUp;
	}

	function getSortIconClass(columnId: string) {
		const sort = $sorting.find(s => s.id === columnId);
		return sort ? '' : 'opacity-50';
	}
</script>

<div class="data-table overflow-x-auto">
	{#if loading}
		<LoadingState type="table" rows={5} columns={columns.length} />
	{:else if isEmpty}
		<EmptyState title={emptyTitle} description={emptyDescription} />
	{:else}
		<table class="table table-zebra table-pin-rows w-full">
			<thead>
				{#each headerGroups as headerGroup}
					<tr>
						{#each headerGroup.headers as header}
							<th 
								class={header.column.getCanSort() ? 'cursor-pointer select-none' : ''}
								onclick={header.column.getToggleSortingHandler()}
							>
								<div class="flex items-center gap-2">
									<span>{header.column.columnDef.header as string}</span>
									{#if header.column.getCanSort()}
										<span class={getSortIconClass(header.column.id)}>
											<svelte:component this={getSortIcon(header.column.id)} size={14} />
										</span>
									{/if}
								</div>
							</th>
						{/each}
					</tr>
				{/each}
			</thead>
			<tbody>
				{#each rows as row}
					<tr 
						class={onRowClick ? 'cursor-pointer hover:bg-base-200' : ''}
						onclick={() => onRowClick?.(row.original)}
					>
						{#each row.getVisibleCells() as cell}
							<td>
								{#if typeof cell.column.columnDef.cell === 'function'}
									{@html cell.column.columnDef.cell(cell.getContext())}
								{:else}
									{cell.getValue()}
								{/if}
							</td>
						{/each}
					</tr>
				{/each}
			</tbody>
		</table>
	{/if}
</div>
