<!-- #region MigrationMappingsTable [C:3] [TYPE Component] [SEMANTICS settings, migration, mappings, table, pagination] -->
<!-- @BRIEF Mappings data table with search, filtering, and pagination for migration sync resources. Isolated from the main MigrationSettings to keep each module < 400 lines. -->
<!-- @LAYER UI -->
<!-- @RELATION DEPENDS_ON -> [EXT:frontend:api_module] -->
<!-- @RELATION BINDS_TO -> [EXT:backend:/migration/mappings-data] -->
<!-- @PRE: API client initialized, refreshKey provided by parent. -->
<!-- @POST: User can search, filter by environment/type, and paginate through resource mappings. -->
<!-- @UX_STATE Loading -> Loading indicator in table body, refresh button disabled. -->
<!-- @UX_STATE Loaded -> Table rows with resource name, type, UUID, remote ID, environment. -->
<!-- @UX_STATE Empty -> "No mappings" row. -->
<!-- @UX_REACTIVITY Props -> refreshKey triggers reload via $effect. -->
<script lang="ts">
  import { t } from "$lib/i18n/index.svelte.js";
  import { api } from "$lib/api.js";

  let { refreshKey = 0 } = $props();

  let displayMappings = $state([]);
  let mappingsTotal = $state(0);
  let mappingsPage = $state(0);
  let mappingsPageSize = $state(25);
  let mappingsSearch = $state("");
  let mappingsEnvFilter = $state("");
  let mappingsTypeFilter = $state("");
  let isLoading = $state(false);
  let searchTimeout = null;

  let mappingsTotalPages = $derived(
    Math.max(1, Math.ceil(mappingsTotal / mappingsPageSize)),
  );

  async function loadMappings() {
    isLoading = true;
    try {
      const skip = mappingsPage * mappingsPageSize;
      let url = `/migration/mappings-data?skip=${skip}&limit=${mappingsPageSize}`;
      if (mappingsSearch)
        url += `&search=${encodeURIComponent(mappingsSearch)}`;
      if (mappingsEnvFilter)
        url += `&env_id=${encodeURIComponent(mappingsEnvFilter)}`;
      if (mappingsTypeFilter)
        url += `&resource_type=${encodeURIComponent(mappingsTypeFilter)}`;
      const res = await api.requestApi(url);
      displayMappings = res.items || [];
      mappingsTotal = res.total || 0;
    } catch (err) {
      console.error("[MigrationMappingsTable] Failed to load mappings:", err);
    } finally {
      isLoading = false;
    }
  }

  function onSearchInput() {
    clearTimeout(searchTimeout);
    searchTimeout = setTimeout(() => {
      mappingsPage = 0;
      loadMappings();
    }, 300);
  }

  function onFilterChange() {
    mappingsPage = 0;
    loadMappings();
  }

  function goToPage(page) {
    if (page < 0 || page >= mappingsTotalPages) return;
    mappingsPage = page;
    loadMappings();
  }

  // Load on mount and whenever refreshKey changes (parent triggers after sync or refresh)
  $effect(() => {
    refreshKey;
    loadMappings();
  });
</script>

<div class="bg-gray-50 p-6 rounded-lg border border-gray-200">
  <h3 class="text-lg font-medium mb-4 flex items-center justify-between">
    <span>
      {$t.settings?.synchronized_resources}
      <span class="text-sm font-normal text-gray-500"
        >({mappingsTotal})</span
      >
    </span>
    <button
      onclick={() => loadMappings()}
      class="text-sm text-indigo-600 hover:text-indigo-800 flex items-center gap-1"
      disabled={isLoading}
    >
      <svg
        class="w-4 h-4 {isLoading ? 'animate-spin' : ''}"
        fill="none"
        stroke="currentColor"
        viewBox="0 0 24 24"
        ><path
          stroke-linecap="round"
          stroke-linejoin="round"
          stroke-width="2"
          d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"
        ></path></svg
      >
      {$t.common?.refresh}
    </button>
  </h3>

  <!-- Search and Filters -->
  <div class="flex flex-wrap gap-3 mb-4">
    <div class="flex-1 min-w-[200px]">
      <input
        type="text"
        bind:value={mappingsSearch}
        oninput={onSearchInput}
        placeholder={$t.settings?.search_by_name_or_uuid}
        class="w-full px-3 py-2 border border-gray-300 rounded-md text-sm focus:ring-indigo-500 focus:border-indigo-500"
      />
    </div>
    <select
      bind:value={mappingsEnvFilter}
      onchange={onFilterChange}
      class="px-3 py-2 border border-gray-300 rounded-md text-sm bg-white focus:ring-indigo-500 focus:border-indigo-500"
    >
      <option value="">{$t.settings?.all_environments}</option>
      <option value="ss1">ss1</option>
      <option value="ss2">ss2</option>
    </select>
    <select
      bind:value={mappingsTypeFilter}
      onchange={onFilterChange}
      class="px-3 py-2 border border-gray-300 rounded-md text-sm bg-white focus:ring-indigo-500 focus:border-indigo-500"
    >
      <option value="">{$t.settings?.all_types}</option>
      <option value="chart">{$t.settings?.type_chart}</option>
      <option value="dataset">{$t.nav?.datasets}</option>
      <option value="dashboard">{$t.nav?.dashboards}</option>
    </select>
  </div>

  <div class="overflow-x-auto border border-gray-200 rounded-lg">
    <table class="min-w-full divide-y divide-gray-200 text-sm">
      <thead class="bg-gray-100">
        <tr>
          <th
            class="px-6 py-3 text-left font-medium text-gray-500 uppercase tracking-wider"
            >{$t.settings?.resource_name}</th
          >
          <th
            class="px-6 py-3 text-left font-medium text-gray-500 uppercase tracking-wider"
            >{$t.settings?.type}</th
          >
          <th
            class="px-6 py-3 text-left font-medium text-gray-500 uppercase tracking-wider"
            >UUID</th
          >
          <th
            class="px-6 py-3 text-left font-medium text-gray-500 uppercase tracking-wider"
            >{$t.settings?.target_id}</th
          >
          <th
            class="px-6 py-3 text-left font-medium text-gray-500 uppercase tracking-wider"
            >{$t.dashboard?.environment}</th
          >
        </tr>
      </thead>
      <tbody class="bg-white divide-y divide-gray-200">
        {#if isLoading && displayMappings.length === 0}
          <tr
            ><td
              colspan="5"
              class="px-6 py-8 text-center text-gray-500"
              >{$t.settings?.loading_mappings}</td
            ></tr
          >
        {:else if displayMappings.length === 0}
          <tr
            ><td
              colspan="5"
              class="px-6 py-8 text-center text-gray-500"
              >{mappingsSearch ||
              mappingsEnvFilter ||
              mappingsTypeFilter
                ? $t.settings?.no_matching_resources
                : $t.settings?.no_synchronized_resources}</td
            ></tr
          >
        {:else}
          {#each displayMappings as mapping}
            <tr class="hover:bg-gray-50">
              <td
                class="px-6 py-4 whitespace-nowrap font-medium text-gray-900"
                >{mapping.resource_name ||
                  $t.common?.not_available}</td
              >
              <td class="px-6 py-4 whitespace-nowrap"
                ><span
                  class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full {mapping.resource_type ===
                  'chart'
                    ? 'bg-blue-100 text-blue-800'
                    : mapping.resource_type === 'dataset'
                      ? 'bg-green-100 text-green-800'
                      : 'bg-purple-100 text-purple-800'}"
                  >{mapping.resource_type}</span
                ></td
              >
              <td
                class="px-6 py-4 whitespace-nowrap font-mono text-xs text-gray-500"
                >{mapping.uuid}</td
              >
              <td
                class="px-6 py-4 whitespace-nowrap font-mono text-xs font-bold text-gray-700"
                >{mapping.remote_id}</td
              >
              <td class="px-6 py-4 whitespace-nowrap text-gray-500"
                >{mapping.environment_id}</td
              >
            </tr>
          {/each}
        {/if}
      </tbody>
    </table>
  </div>

  <!-- Pagination Controls -->
  {#if mappingsTotal > mappingsPageSize}
    <div class="flex items-center justify-between mt-4 text-sm text-gray-600">
      <span
        >{($t.dashboard?.showing)
          .replace("{start}", String(mappingsPage * mappingsPageSize + 1))
          .replace(
            "{end}",
            String(
              Math.min(
                (mappingsPage + 1) * mappingsPageSize,
                mappingsTotal,
              ),
            ),
          )
          .replace("{total}", String(mappingsTotal))}</span
      >
      <div class="flex items-center gap-2">
        <button
          onclick={() => goToPage(0)}
          disabled={mappingsPage === 0}
          class="px-2 py-1 rounded border {mappingsPage === 0
            ? 'bg-gray-100 text-gray-400 cursor-not-allowed'
            : 'bg-white hover:bg-gray-50 text-gray-700'}">«</button
        >
        <button
          onclick={() => goToPage(mappingsPage - 1)}
          disabled={mappingsPage === 0}
          class="px-2 py-1 rounded border {mappingsPage === 0
            ? 'bg-gray-100 text-gray-400 cursor-not-allowed'
            : 'bg-white hover:bg-gray-50 text-gray-700'}">‹</button
        >
        <span class="px-3 py-1 font-medium"
          >{mappingsPage + 1} / {mappingsTotalPages}</span
        >
        <button
          onclick={() => goToPage(mappingsPage + 1)}
          disabled={mappingsPage >= mappingsTotalPages - 1}
          class="px-2 py-1 rounded border {mappingsPage >=
          mappingsTotalPages - 1
            ? 'bg-gray-100 text-gray-400 cursor-not-allowed'
            : 'bg-white hover:bg-gray-50 text-gray-700'}">›</button
        >
        <button
          onclick={() => goToPage(mappingsTotalPages - 1)}
          disabled={mappingsPage >= mappingsTotalPages - 1}
          class="px-2 py-1 rounded border {mappingsPage >=
          mappingsTotalPages - 1
            ? 'bg-gray-100 text-gray-400 cursor-not-allowed'
            : 'bg-white hover:bg-gray-50 text-gray-700'}">»</button
        >
      </div>
    </div>
  {/if}
</div>
<!-- #endregion MigrationMappingsTable -->
