<!-- #region DatasetList [C:4] [TYPE Component] [SEMANTICS ui,dataset,card,list,pagination] -->
<!-- @BRIEF Renders paginated dataset cards with mapping progress bars, checkboxes, and quick actions. -->
<!-- @RATIONALE Action buttons switched from bg-primary solid to border-outline style, card padding reduced from p-3 to p-2.5, row gap from gap-3 to gap-2.5 — fixes "huge buttons" visual complaint. -->
<!-- @REJECTED Solid blue action buttons rejected — too visually heavy on each card line. -->
<!-- @RELATION BINDS_TO -> [EXT:frontend:environmentContextStore] -->
<!-- @UX_STATE Loading -> Skeleton cards. -->
<!-- @UX_STATE Loaded -> Cards with progress bars. -->
<!-- @UX_STATE Empty -> "No datasets found" after search/filter. -->
<!-- @UX_REACTIVITY Props -> datasets, selectedIds, isLoading, error, total, page, totalPages, pageSize, onselect, onaction, onpagechange, onsearch, oncheckbox -->
<script lang="ts">
  import { t } from "$lib/i18n/index.svelte.js";

  let {
    datasets = [],
    selectedIds = new Set(),
    isLoading = false,
    error = null,
    total = 0,
    page = 1,
    totalPages = 1,
    pageSize = 10,
    onselect,
    onaction,
    onpagechange,
    onsearch,
    oncheckbox,
    searchQuery = "",
  } = $props();

  let localSearch = $state(searchQuery);

  function getProgressClass(mapped, total) {
    if (!total || !mapped) return "bg-gray-200";
    const pct = (mapped / total) * 100;
    if (pct === 100) return "bg-green-500";
    if (pct >= 50) return "bg-yellow-400";
    return "bg-blue-400";
  }

  function handleCardClick(dataset, e) {
    if (e.target.closest("input[type=checkbox], button")) return;
    onselect?.(dataset.id);
  }

  function handleCheckboxChange(dataset, e) {
    const checked = e.target.checked;
    oncheckbox?.(dataset, checked);
  }

  function handleSearchInput(e) {
    localSearch = e.target.value;
    onsearch?.(localSearch);
  }
</script>

<!-- Search -->
<div class="flex items-center justify-between mb-3 gap-3">
  <input
    type="text"
    class="px-3 py-1.5 border border-gray-300 rounded bg-white text-sm focus:outline-none focus:ring-2 focus:ring-primary/30 w-full max-w-xs"
    placeholder={$t.datasets?.search_placeholder ?? "Search datasets..."}
    value={localSearch}
    oninput={handleSearchInput}
  />
  <div class="flex gap-2">
    <button
      class="px-2 py-1 text-xs border border-gray-300 rounded hover:bg-gray-50"
      title={$t.datasets?.select_all_tip}
      onclick={() => { selectedIds = new Set(datasets.map(d => d.id)); oncheckbox?.({}, 'all'); }}
    >{$t.datasets?.select_all}</button>
    <button
      class="px-2 py-1 text-xs border border-gray-300 rounded hover:bg-gray-50"
      title={$t.datasets?.deselect_all_tip}
      onclick={() => { selectedIds = new Set(); oncheckbox?.({}, 'clear-all'); }}
    >{$t.datasets?.deselect_all}</button>
  </div>
</div>

<!-- Loading -->
{#if isLoading}
  <div class="space-y-3" aria-busy="true">
    {#each Array(3) as _, _i (_i)}
      <div class="bg-white border border-gray-200 rounded-lg p-4 animate-pulse">
        <div class="h-4 bg-gray-200 rounded w-1/3 mb-2"></div>
        <div class="h-3 bg-gray-200 rounded w-1/4 mb-3"></div>
        <div class="h-2 bg-gray-200 rounded w-full"></div>
      </div>
    {/each}
  </div>
{:else if error}
  <div class="bg-red-50 border border-red-300 text-red-700 px-3 py-2 rounded text-sm">
    {error}
  </div>
{:else if datasets.length === 0}
  <div class="py-8 text-center text-gray-400 text-sm">{$t.datasets?.empty}</div>
{:else}
  <!-- Card Grid -->
  <div class="space-y-1.5">
    {#each datasets as dataset (dataset.id)}
      <div
        class="bg-white border border-gray-200 rounded-lg p-2.5 cursor-pointer hover:border-gray-300 hover:shadow-sm transition-all"
        onclick={(e) => handleCardClick(dataset, e)}
        role="button"
        tabindex="0"
      >
        <div class="flex items-start gap-2.5">
          <!-- Checkbox -->
          <input
            type="checkbox"
            class="mt-0.5 accent-primary shrink-0"
            checked={selectedIds.has(dataset.id)}
            onchange={(e) => handleCheckboxChange(dataset, e)}
          />
          <!-- Content -->
          <div class="flex-1 min-w-0">
            <div class="font-medium text-gray-900 truncate text-sm">{dataset.table_name}</div>
            <div class="text-xs text-gray-500 mt-0.5 flex gap-3 flex-wrap">
              <span>{dataset.schema ?? '-'}</span>
              <span>{dataset.column_count ?? 0} {$t.datasets?.columns?.toLowerCase() ?? 'columns'}</span>
              {#if dataset.metric_count > 0}
                <span>{dataset.metric_count} {$t.datasets?.metric_count ?? 'metrics'}</span>
              {/if}
            </div>
            <!-- Progress bar -->
            {#if dataset.mappedFields?.total}
              <div class="mt-1.5">
                <div class="w-full h-1.5 bg-gray-100 rounded-full overflow-hidden">
                  <div
                    class="h-full rounded-full transition-all {getProgressClass(dataset.mappedFields.mapped, dataset.mappedFields.total)}"
                    style="width: {(dataset.mappedFields.mapped / dataset.mappedFields.total) * 100}%"
                  ></div>
                </div>
                <div class="text-xs text-gray-400 mt-0.5">
                  {dataset.mappedFields.mapped}/{dataset.mappedFields.total} {$t.datasets?.mapped_of_total}
                </div>
              </div>
            {/if}
          </div>
          <!-- Quick actions (icon-only) -->
          <div class="flex gap-1 shrink-0 items-start">
            <button
              class="p-1 border border-gray-300 text-gray-400 rounded hover:bg-gray-50 hover:text-gray-600 transition-colors"
              title={$t.datasets?.map_columns_tip}
              onclick={(e) => { e.stopPropagation(); onaction?.(dataset, 'map_columns'); }}
            >
              <!-- columns/grid icon -->
              <svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                <rect x="3" y="3" width="7" height="7" rx="1"/>
                <rect x="14" y="3" width="7" height="7" rx="1"/>
                <rect x="3" y="14" width="7" height="7" rx="1"/>
                <rect x="14" y="14" width="7" height="7" rx="1"/>
              </svg>
            </button>
            <button
              class="p-1 border border-gray-300 text-gray-400 rounded hover:bg-gray-50 hover:text-gray-600 transition-colors"
              title={$t.datasets?.generate_docs_tip}
              onclick={(e) => { e.stopPropagation(); onaction?.(dataset, 'generate_docs'); }}
            >
              <!-- file/text icon -->
              <svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
                <polyline points="14 2 14 8 20 8"/>
                <line x1="16" y1="13" x2="8" y2="13"/>
                <line x1="16" y1="17" x2="8" y2="17"/>
                <polyline points="10 9 9 9 8 9"/>
              </svg>
            </button>
          </div>
        </div>
      </div>
    {/each}
  </div>

  <!-- Pagination -->
  {#if totalPages > 1}
    <div class="flex items-center justify-between mt-3 pt-3 border-t border-gray-200">
      <span class="text-sm text-gray-500">
        {($t.datasets?.showing ?? 'Showing {start}-{end} of {total}').replace('{start}', String((page - 1) * pageSize + 1)).replace('{end}', String(Math.min(page * pageSize, total))).replace('{total}', String(total))}
      </span>
      <div class="flex gap-1">
        <button class="px-2 py-1 text-xs border rounded {page <= 1 ? 'opacity-50 cursor-not-allowed' : 'hover:bg-gray-50'}" title={$t.datasets?.pagination_first_tip} onclick={() => onpagechange?.(1)} disabled={page <= 1}>«</button>
        <button class="px-2 py-1 text-xs border rounded {page <= 1 ? 'opacity-50 cursor-not-allowed' : 'hover:bg-gray-50'}" title={$t.datasets?.pagination_prev_tip} onclick={() => onpagechange?.(page - 1)} disabled={page <= 1}>‹</button>
        <span class="px-2 py-1 text-xs">{page} / {totalPages}</span>
        <button class="px-2 py-1 text-xs border rounded {page >= totalPages ? 'opacity-50 cursor-not-allowed' : 'hover:bg-gray-50'}" title={$t.datasets?.pagination_next_tip} onclick={() => onpagechange?.(page + 1)} disabled={page >= totalPages}>›</button>
        <button class="px-2 py-1 text-xs border rounded {page >= totalPages ? 'opacity-50 cursor-not-allowed' : 'hover:bg-gray-50'}" title={$t.datasets?.pagination_last_tip} onclick={() => onpagechange?.(totalPages)} disabled={page >= totalPages}>»</button>
      </div>
    </div>
  {/if}
{/if}
<!-- #endregion DatasetList -->