<!--
  What the "N waiting to sync" badge actually stands for.

  These are outgoing changes — watch positions, watched flags — made while the
  server was unreachable and still waiting to reach Jellyfin. They are *not*
  downloads, which is where the badge used to send people looking: the Downloads
  page lists the `downloads` table and structurally cannot show these.

  Rows push themselves on reconnect (DR-131); "Sync now" only asks for that to
  happen immediately.

  TRACES: UR-025 | DR-132
-->
<script lang="ts">
  import { onMount } from "svelte";
  import { commands, type SyncQueueItem } from "$lib/api/bindings";
  import { syncService } from "$lib/services/syncService";
  import { pendingSyncCount } from "$lib/stores/appState";
  import { isConnected } from "$lib/stores/connectivity";
  import {
    describeOperation,
    describeSubject,
    isStuck,
    summarize,
    sortForDisplay,
  } from "$lib/services/pendingSync.logic";

  let items = $state<SyncQueueItem[]>([]);
  let loading = $state(true);
  let syncing = $state(false);
  let error = $state<string | null>(null);
  let lastResult = $state<string | null>(null);

  const summary = $derived(summarize(items));

  export async function refresh() {
    try {
      loading = true;
      error = null;
      items = sortForDisplay(await syncService.getPending());
      pendingSyncCount.set(items.length);
    } catch (err) {
      error = err instanceof Error ? err.message : String(err);
    } finally {
      loading = false;
    }
  }

  onMount(refresh);

  async function syncNow() {
    try {
      syncing = true;
      error = null;
      const report = await commands.syncProcessPending();
      lastResult =
        report.pushed > 0
          ? `Sent ${report.pushed} update${report.pushed === 1 ? "" : "s"}.`
          : "Nothing could be sent — the server is still unreachable.";
      await refresh();
    } catch (err) {
      error = err instanceof Error ? err.message : String(err);
    } finally {
      syncing = false;
    }
  }

  function formatQueuedAt(createdAt: string | null): string {
    if (!createdAt) return "";
    const parsed = Date.parse(createdAt);
    return Number.isNaN(parsed) ? "" : new Date(parsed).toLocaleString();
  }
</script>

<div class="space-y-4">
  <p class="text-sm text-gray-400">
    Changes made while the server was unreachable — watch positions and watched
    flags — waiting to reach Jellyfin. They send themselves when the server comes
    back. This is not the download queue; downloaded media lives under Downloads.
  </p>

  {#if loading}
    <p class="py-6 text-center text-sm text-gray-400">Loading queued updates…</p>
  {:else if items.length === 0}
    <p class="py-6 text-center text-sm text-gray-500">Everything is synced.</p>
  {:else}
    <div class="flex flex-wrap items-center gap-3">
      <button
        onclick={syncNow}
        disabled={syncing || !$isConnected}
        class="rounded-lg bg-[var(--color-jellyfin)] px-4 py-2 text-sm font-medium text-white transition hover:opacity-90 disabled:cursor-not-allowed disabled:opacity-40"
        title={$isConnected ? "Send these now" : "Needs a reachable server"}
      >
        {syncing ? "Sending…" : "Sync now"}
      </button>
      {#if summary.stuck > 0}
        <span class="text-xs text-amber-400">
          {summary.stuck} failed and will be retried
        </span>
      {/if}
      {#if lastResult}
        <span class="text-xs text-gray-400">{lastResult}</span>
      {/if}
    </div>

    <ul class="space-y-2">
      {#each items as item (item.id)}
        <li
          class="rounded-lg border-l-4 bg-[var(--color-surface)] p-3 {isStuck(item)
            ? 'border-amber-500/60'
            : 'border-gray-600/60'}"
        >
          <div class="flex items-start justify-between gap-3">
            <div class="min-w-0">
              <p class="truncate text-sm font-medium text-white">
                {describeOperation(item.operation)}
              </p>
              <p class="truncate text-xs text-gray-400">{describeSubject(item)}</p>
              {#if item.errorMessage}
                <p class="mt-1 text-xs text-amber-400">
                  {item.errorMessage}{item.retryCount > 0 ? ` (attempt ${item.retryCount})` : ""}
                </p>
              {/if}
            </div>
            <span class="shrink-0 text-[11px] text-gray-500">
              {formatQueuedAt(item.createdAt)}
            </span>
          </div>
        </li>
      {/each}
    </ul>
  {/if}

  {#if error}
    <p class="text-sm text-red-400">{error}</p>
  {/if}
</div>
