<script lang="ts" generics="T">
	/* eslint-disable no-undef */
	import { ArrowUp, ArrowDown } from 'lucide-svelte';

	interface Column<T> {
		key: keyof T;
		label: string;
		sortable?: boolean;
		format?: (value: T[keyof T], row: T) => string;
		render?: (value: T[keyof T], row: T) => unknown;
		align?: 'left' | 'center' | 'right';
		class?: string;
		width?: string;
	}

	interface Props {
		data: T[];
		columns: Column<T>[];
		class?: string;
		striped?: boolean;
		hoverable?: boolean;
		compact?: boolean;
		fixedLayout?: boolean;
	}

	let {
		data,
		columns,
		class: className = '',
		striped = false,
		hoverable = true,
		compact = false,
		fixedLayout = false
	}: Props = $props();

	let sortKey = $state<keyof T | null>(null);
	let sortDirection = $state<'asc' | 'desc'>('asc');

	const handleSort = (column: Column<T>) => {
		if (!column.sortable) return;

		if (sortKey === column.key) {
			sortDirection = sortDirection === 'asc' ? 'desc' : 'asc';
		} else {
			sortKey = column.key;
			sortDirection = 'asc';
		}
	};

	const sortedData = $derived(
		!sortKey
			? data
			: [...data].sort((a, b) => {
					const aVal = a[sortKey as keyof T];
					const bVal = b[sortKey as keyof T];

					if (aVal === bVal) return 0;

					const comparison = aVal < bVal ? -1 : 1;
					return sortDirection === 'asc' ? comparison : -comparison;
				})
	);

	const getValue = (row: T, column: Column<T>) => {
		const value = row[column.key];
		if (column.format) {
			return column.format(value, row);
		}
		return value;
	};
</script>

<div class="overflow-x-auto {className}">
	<table class="w-full border-collapse" style={fixedLayout ? 'table-layout: fixed;' : ''}>
		<thead>
			<tr class="border-b border-white/10 bg-void">
				{#each columns as column}
					<th
						class="px-4 text-left text-xs font-semibold uppercase tracking-wider text-white/60 {compact
							? 'py-2'
							: 'py-3'} {column.sortable
							? 'cursor-pointer transition-colors hover:bg-neon-blue/10 hover:text-neon-blue'
							: ''} {column.class || ''}"
						class:text-center={column.align === 'center'}
						class:text-right={column.align === 'right'}
						style={column.width ? `width: ${column.width}` : ''}
						onclick={() => handleSort(column)}
					>
						<div
							class="flex items-center gap-2"
							class:justify-end={column.align === 'right'}
							class:justify-center={column.align === 'center'}
						>
							<span>{column.label}</span>
							{#if column.sortable}
								<div class="flex flex-col">
									<ArrowUp
										class="h-3 w-3 {sortKey === column.key && sortDirection === 'asc'
											? 'text-neon-blue'
											: 'text-white/30'}"
									/>
									<ArrowDown
										class="-mt-1 h-3 w-3 {sortKey === column.key && sortDirection === 'desc'
											? 'text-neon-blue'
											: 'text-white/30'}"
									/>
								</div>
							{/if}
						</div>
					</th>
				{/each}
			</tr>
		</thead>
		<tbody>
			{#each sortedData as row, index}
				<tr
					class="border-b border-white/5 transition-colors {hoverable
						? 'hover:bg-neon-blue/5'
						: ''} {striped && index % 2 === 1 ? 'bg-white/[0.02]' : ''}"
				>
					{#each columns as column}
						<td
							class="px-4 text-white/80 {compact ? 'py-2' : 'py-3'} {column.class || ''}"
							class:text-center={column.align === 'center'}
							class:text-right={column.align === 'right'}
						>
							{#if column.render}
								{@html column.render(row[column.key], row)}
							{:else}
								{getValue(row, column)}
							{/if}
						</td>
					{/each}
				</tr>
			{/each}
		</tbody>
	</table>
</div>

<style>
	/* Style links and buttons within table cells */
	:global(td a) {
		color: rgb(0, 212, 255);
		transition: color 0.2s;
	}
	:global(td a:hover) {
		color: rgb(0, 170, 204);
	}
	:global(td .btn-primary) {
		background-color: rgb(0, 212, 255);
		color: rgb(10, 10, 15);
		border: none;
		padding: 0.375rem 0.75rem;
		border-radius: 0.5rem;
		font-weight: 600;
		font-size: 0.875rem;
		transition: all 0.2s;
	}
	:global(td .btn-primary:hover) {
		box-shadow: 0 0 15px rgba(0, 212, 255, 0.4);
		transform: scale(1.02);
	}
	/* Neon badge styling for result badges */
	:global(td .badge-success) {
		background-color: rgba(0, 255, 136, 0.1);
		color: rgb(0, 255, 136);
		border: 1px solid rgba(0, 255, 136, 0.3);
	}
	:global(td .badge-error) {
		background-color: rgba(255, 51, 102, 0.1);
		color: rgb(255, 51, 102);
		border: 1px solid rgba(255, 51, 102, 0.3);
	}
	:global(td .badge-warning) {
		background-color: rgba(255, 215, 0, 0.1);
		color: rgb(255, 215, 0);
		border: 1px solid rgba(255, 215, 0, 0.3);
	}
	:global(td .badge) {
		padding: 0.25rem 0.5rem;
		border-radius: 9999px;
		font-size: 0.75rem;
		font-weight: 500;
	}
</style>
