<script lang="ts">
  import { GripVertical, X } from 'lucide-svelte';
  import { draggable, type DragEventData } from '@neodrag/svelte';
  import type { TrackRef } from '$lib/api/types';
  import { playFromQueueIndex, removeFromQueue, moveQueueItem } from '$lib/player/store.svelte';
  import { coverUrl, FALLBACK_COVER } from '$lib/media/covers';
  import { offsetToDelta } from './queue-row-math';
  import LikeButton from './LikeButton.svelte';

  let { track, index, isCurrent } = $props<{
    track: TrackRef;
    index: number;
    isCurrent: boolean;
  }>();

  let measuredRowHeight = 64; // sensible default; replaced on dragStart

  function handleDragStart(data: DragEventData) {
    // The action's `data.rootNode` is the element use:draggable was applied to.
    const rect = data.rootNode.getBoundingClientRect();
    if (rect.height > 0) measuredRowHeight = rect.height;
  }

  function handleBodyClick() {
    if (isCurrent) return;
    playFromQueueIndex(index);
  }

  function handleRemove() {
    removeFromQueue(index);
  }

  function handleDragEnd(data: DragEventData) {
    const delta = offsetToDelta(data.offsetY, measuredRowHeight);
    if (delta === 0) return;
    moveQueueItem(index, index + delta);
  }

  function handleHandleKeydown(e: KeyboardEvent) {
    if (e.key === 'ArrowUp') {
      e.preventDefault();
      moveQueueItem(index, index - 1);
    } else if (e.key === 'ArrowDown') {
      e.preventDefault();
      moveQueueItem(index, index + 1);
    } else if (e.key === ' ' || e.key === 'Enter') {
      // Reorder activates via arrow keys, not Space/Enter. Prevent
      // default so Space doesn't scroll the queue list and Enter doesn't
      // fire the button's no-op click.
      e.preventDefault();
    }
  }
</script>

<div
  use:draggable={{ axis: 'y', bounds: 'parent', onDragStart: handleDragStart, onDragEnd: handleDragEnd }}
  class="flex items-center gap-2 border-b border-border px-3 py-2 h-16
         {isCurrent ? 'border-l-2 border-l-accent bg-surface-hover' : ''}"
>
  <!--
    The album art is the grab surface (#2395). The grip used to occupy its own
    column in every row; it now sits OVER the art, so it costs no horizontal
    space at all. `use:draggable` is on the row (above), so dragging already
    worked from anywhere — the grip's real jobs are being the visual cue and
    the keyboard target, and both survive here.

    It stays VISIBLE at rest, just quiet — it is the only thing that says this
    list can be reordered at all, so hiding it until hover would trade the
    operator's space complaint for a discoverability one (rule #24), and would
    leave nothing for touch, which has no hover. The scrim only appears on
    hover/focus so the artwork stays legible the rest of the time; the drop
    shadow is what keeps the glyph readable over pale covers without one.
  -->
  <div class="relative h-10 w-10 flex-shrink-0">
    <img
      src={coverUrl(track.album_id)}
      alt=""
      onerror={(e) => ((e.currentTarget as HTMLImageElement).src = FALLBACK_COVER)}
      class="h-10 w-10 rounded object-cover"
    />
    <button
      type="button"
      aria-label="Reorder track (use arrow keys)"
      aria-keyshortcuts="ArrowUp ArrowDown"
      onkeydown={handleHandleKeydown}
      class="group absolute inset-0 flex cursor-grab items-center justify-center rounded
             text-white/70 transition hover:bg-black/45 hover:text-white
             focus-visible:bg-black/45 focus-visible:text-white
             focus-visible:outline focus-visible:outline-2 focus-visible:outline-accent"
      style="filter: drop-shadow(0 1px 1px rgb(0 0 0 / 0.9))"
    >
      <GripVertical size={16} />
    </button>
  </div>

  <button
    type="button"
    onclick={handleBodyClick}
    class="flex-1 text-left min-w-0 {isCurrent ? 'cursor-default' : 'cursor-pointer'}"
    aria-label={isCurrent ? `Now playing — ${track.title}` : `Play ${track.title}`}
  >
    <div class="flex items-center gap-2 min-w-0">
      {#if isCurrent}
        <span class="text-xs text-accent uppercase tracking-wide flex-shrink-0">Now playing</span>
      {/if}
      <span class="font-medium truncate text-text-primary">{track.title}</span>
    </div>
    <div class="text-xs text-text-secondary truncate">{track.artist_name}</div>
  </button>

  <LikeButton entityType="track" entityId={track.id} />

  <button
    type="button"
    onclick={handleRemove}
    aria-label="Remove from queue"
    class="text-text-secondary hover:text-text-primary flex-shrink-0"
  >
    <X size={16} />
  </button>
</div>
