<script>
  /**
   * @typedef {Object} Column
   * @property {string} key - Column key (accessor)
   * @property {string} label - Column header label
   * @property {string} [class] - CSS classes for the column
   * @property {Function} [render] - Custom render function
   */

  /**
   * @typedef {Object} Props
   * @property {Array<Column>} columns - Column definitions
   * @property {Array<Object>} data - Table data rows
   * @property {boolean} [loading] - Whether data is loading
   * @property {string} [emptyMessage] - Message when no data
   * @property {boolean} [striped] - Whether to stripe rows
   * @property {boolean} [hover] - Whether rows have hover effect
   * @property {boolean} [bordered] - Whether table has borders
   * @property {function} [onRowClick] - Callback when row is clicked
   * @property {string} [class] - Additional CSS classes
   */

  /** @type {Props & { cell?: import('svelte').Snippet<{ column: Column, row: Object, value: any }> }} */
  let {
    columns,
    data,
    loading = false,
    emptyMessage = 'No data available',
    striped = false,
    hover = true,
    bordered = true,
    onRowClick = null,
    class: className = '',
    cell,
  } = $props();

  /**
   * Get value from row object using column key (supports nested keys)
   * @param {Object} row - Data row
   * @param {string} key - Column key
   * @returns {any}
   */
  function getValue(row, key) {
    if (!key) return '';
    const keys = key.split('.');
    let value = row;
    for (const k of keys) {
      if (value == null) return '';
      value = value[k];
    }
    return value ?? '';
  }

  /**
   * Handle row click
   * @param {Object} row - Clicked row
   * @param {number} index - Row index
   */
  function handleRowClick(row, index) {
    if (onRowClick) {
      onRowClick(row, index);
    }
  }
</script>

<div class="overflow-x-auto {className}">
  <table class="table table-compact w-full" class:table-zebra={striped} class:table-bordered={bordered}>
    <thead>
      <tr class="bg-base-200">
        {#each columns as column}
          <th class="text-sm font-semibold {column.class || ''}">
            {column.label}
          </th>
        {/each}
      </tr>
    </thead>
    
    <tbody>
      {#if loading}
        <tr>
          <td colspan={columns.length} class="text-center py-8">
            <span class="loading loading-spinner loading-md text-primary"></span>
            <p class="text-sm text-gray-500 mt-2">Loading...</p>
          </td>
        </tr>
      {:else if data.length === 0}
        <tr>
          <td colspan={columns.length} class="text-center py-8 text-gray-500">
            {emptyMessage}
          </td>
        </tr>
      {:else}
        {#each data as row, index}
          <tr
            class:bg-base-100={true}
            class:hover={hover}
            class:cursor-pointer={!!onRowClick}
            class:bg-base-200={index % 2 === 1 && striped}
            onclick={() => handleRowClick(row, index)}
            onkeydown={(e) => e.key === 'Enter' && handleRowClick(row, index)}
            tabindex={onRowClick ? 0 : -1}
            role={onRowClick ? 'button' : undefined}
          >
            {#each columns as column}
              <td class="text-sm {column.class || ''}">
                {#if cell}
                  {@render cell({ column, row, value: getValue(row, column.key), index })}
                {:else if column.render}
                  {@render column.render(row)}
                {:else}
                  {getValue(row, column.key)}
                {/if}
              </td>
            {/each}
          </tr>
        {/each}
      {/if}
    </tbody>
  </table>
</div>
