<script lang="ts">
  import { playerController } from "$lib/player";
  import { truncateMiddle } from "$lib/utils/truncateMiddle";
  import type { PlayTracksContext } from "$lib/api/bindings";
  import { goto } from "$app/navigation";
  import { queue } from "$lib/stores/queue";
  import { currentMedia } from "$lib/stores/player";
  import { toast } from "$lib/stores/toast";
  import type { MediaItem } from "$lib/api/types";
  import DownloadButton from "./DownloadButton.svelte";
  import Portal from "$lib/components/Portal.svelte";
  import AddToPlaylistModal from "$lib/components/playlist/AddToPlaylistModal.svelte";
  import { calculateMenuPosition, type MenuPosition } from "$lib/utils/menuPosition";
  import { formatDuration } from "$lib/utils/duration";

  /** Queue context for remote transfer - what type of queue is this? */
  export type QueueContext =
    | { type: "album"; albumId: string; albumName: string }
    | { type: "playlist"; playlistId: string; playlistName: string }
    | { type: "custom" };

  interface Props {
    tracks: MediaItem[];
    loading?: boolean;
    showAlbum?: boolean;
    showArtist?: boolean;
    showDownload?: boolean;
    /** Context for the queue - used for remote playback transfer */
    context?: QueueContext;
    onTrackClick?: (track: MediaItem, index: number) => void | Promise<void>;
  }

  let {
    tracks,
    loading = false,
    showAlbum = true,
    showArtist = true,
    showDownload = false,
    context,
    onTrackClick
  }: Props = $props();

  let isPlayingTrack = $state<string | null>(null);
  let openMenuId = $state<string | null>(null);
  let menuPosition = $state<MenuPosition | null>(null);
  let addToPlaylistTrackId = $state<string | null>(null);

  // Track which track is currently playing (from player store)
  const currentlyPlayingId = $derived($currentMedia?.id ?? null);

  // Default internal handler for playing tracks directly
  async function defaultHandleTrackClick(track: MediaItem, index: number) {
    try {
      isPlayingTrack = track.id;

      // If this is an album, use the backend album command (more efficient)
      if (context && context.type === "album") {
        console.log(`[TrackList] Playing track: "${track.name}" (ID: ${track.id}, index in list: ${index})`);
        await playerController.playAlbumTrack({
          albumId: context.albumId,
          albumName: context.albumName,
          trackId: track.id,
          shuffle: false,
        });
        return;
      }

      // Use new backend command for non-album contexts (playlists, custom queues, etc.)
      // Backend handles all metadata fetching and queue building
      const trackIds = tracks.map((t) => t.id);

      // Determine context for queue
      let playContext: PlayTracksContext;
      if (context?.type === "playlist") {
        playContext = {
          type: "playlist",
          playlistId: context.playlistId,
          playlistName: context.playlistName,
        };
      } else {
        playContext = { type: "custom", label: null };
      }

      await playerController.playTracks({
        trackIds,
        startIndex: index,
        shuffle: false,
        context: playContext,
      });

      // Queue will auto-update from Rust backend event
    } catch (e) {
      const errorMessage = e instanceof Error ? e.message : 'Unknown error';
      console.error("Failed to play track:", errorMessage);
      toast.error(`Failed to play track: ${errorMessage}`, 5000);
    } finally {
      isPlayingTrack = null;
    }
  }

  // Unified handler that delegates to custom callback or default
  async function handleTrackClick(track: MediaItem, index: number) {
    if (onTrackClick) {
      await onTrackClick(track, index);
    } else {
      await defaultHandleTrackClick(track, index);
    }
  }


  function toggleMenu(trackId: string, buttonElement: HTMLElement, e: Event) {
    e.stopPropagation();

    if (openMenuId === trackId) {
      openMenuId = null;
      menuPosition = null;
    } else {
      openMenuId = trackId;
      menuPosition = calculateMenuPosition(buttonElement, 160, 120);
    }
  }

  function closeMenu() {
    if (openMenuId !== null) {
      openMenuId = null;
      menuPosition = null;
    }
  }

  function handleArtistClick(artistId: string, e: Event) {
    e.stopPropagation();
    goto(`/library/${artistId}`);
  }

  function handleAlbumClick(albumId: string | null | undefined, e: Event) {
    if (!albumId) return;
    e.stopPropagation();
    goto(`/library/${albumId}`);
  }

  async function addToQueue(track: MediaItem, position: "next" | "end", e: Event) {
    e.stopPropagation();
    closeMenu();

    try {
      // Queue store now handles everything in Rust - just pass the track
      await queue.addToQueue(track, position);
      console.log(`Added "${track.name}" to queue (${position})`);
    } catch (e) {
      console.error("Failed to add to queue:", e);
    }
  }
</script>

{#if loading}
  <div class="space-y-2">
    {#each Array(10) as _}
      <div
        class="animate-pulse bg-[var(--color-surface)] rounded-lg p-4 flex items-center gap-4"
      >
        <div class="w-12 h-12 bg-gray-700 rounded"></div>
        <div class="flex-1 space-y-2">
          <div class="h-4 bg-gray-700 rounded w-1/3"></div>
          <div class="h-3 bg-gray-700 rounded w-1/4"></div>
        </div>
      </div>
    {/each}
  </div>
{:else if tracks.length === 0}
  <div class="text-center py-12 text-gray-400">
    <p>No tracks found</p>
  </div>
{:else}
  <!-- Table Header (Desktop) -->
  <div
    class="hidden md:grid gap-4 px-4 py-2 text-sm text-gray-400 border-b border-gray-700"
    style="grid-template-columns: auto 2fr {showArtist ? '1.5fr' : ''} {showAlbum
      ? '1.5fr'
      : ''} auto {showDownload ? 'auto' : ''} auto;"
  >
    <div class="w-12">#</div>
    <div>Title</div>
    {#if showArtist}
      <div>Artist</div>
    {/if}
    {#if showAlbum}
      <div>Album</div>
    {/if}
    <div class="text-right">Duration</div>
    {#if showDownload}
      <div class="w-12"></div>
    {/if}
    <div class="w-10"></div>
  </div>

  <!-- Track Rows -->
  <div class="space-y-1">
    {#each tracks as track, index (track.id)}
      <div data-grid-index={index} class="w-full group hover:bg-[var(--color-surface-hover)] rounded-lg transition-colors relative {currentlyPlayingId === track.id ? 'bg-[var(--color-jellyfin)]/10 border-l-4 border-[var(--color-jellyfin)]' : ''}">
        <!-- Desktop View -->
        <button
          onclick={() => handleTrackClick(track, index)}
          disabled={isPlayingTrack !== null}
          class="hidden md:grid gap-4 px-4 py-3 items-center w-full text-left cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed"
          style="grid-template-columns: auto 2fr {showArtist ? '1.5fr' : ''} {showAlbum
            ? '1.5fr'
            : ''} auto {showDownload ? 'auto' : ''} auto;"
        >
          <!-- Index/Play Button -->
          <div class="w-12 flex items-center justify-center">
            {#if isPlayingTrack === track.id}
              <div class="w-5 h-5 border-2 border-[var(--color-jellyfin)] border-t-transparent rounded-full animate-spin"></div>
            {:else}
              <span class="group-hover:hidden text-gray-400">{index + 1}</span>
              <svg
                class="hidden group-hover:block w-5 h-5 text-white"
                fill="currentColor"
                viewBox="0 0 24 24"
              >
                <path d="M8 5v14l11-7z" />
              </svg>
            {/if}
          </div>

          <!-- Title -->
          <div class="min-w-0 flex items-center gap-2">
            {#if currentlyPlayingId === track.id}
              <div class="flex flex-col items-center justify-center">
                <div class="w-1 h-1 bg-[var(--color-jellyfin)] rounded-full animate-pulse"></div>
                <div class="w-1 h-1 bg-[var(--color-jellyfin)] rounded-full animate-pulse" style="animation-delay: 150ms"></div>
                <div class="w-1 h-1 bg-[var(--color-jellyfin)] rounded-full animate-pulse" style="animation-delay: 300ms"></div>
              </div>
            {/if}
            <span
              class="text-white font-medium truncate group-hover:text-[var(--color-jellyfin)] transition-colors {currentlyPlayingId === track.id ? 'text-[var(--color-jellyfin)]' : ''}"
            >
              {truncateMiddle(track.name, 48)}
            </span>
          </div>

          <!-- Artist -->
          {#if showArtist}
            <div class="text-gray-300 truncate flex flex-wrap items-center gap-1">
              {#if track.artistItems && track.artistItems.length > 0}
                {#each track.artistItems as artist, idx}
                  <span
                    role="button"
                    tabindex="0"
                    onclick={(e) => handleArtistClick(artist.id, e)}
                    onkeydown={(e) => e.key === 'Enter' && handleArtistClick(artist.id, e)}
                    class="text-[var(--color-jellyfin)] hover:underline truncate cursor-pointer"
                  >
                    {artist.name}
                  </span>
                  {#if idx < track.artistItems.length - 1}
                    <span>,</span>
                  {/if}
                {/each}
              {:else}
                {track.artists?.join(", ") || "-"}
              {/if}
            </div>
          {/if}

          <!-- Album -->
          {#if showAlbum}
            <div class="text-gray-300 truncate">
              {#if track.albumId}
                <span
                  role="button"
                  tabindex="0"
                  onclick={(e) => handleAlbumClick(track.albumId, e)}
                  onkeydown={(e) => e.key === 'Enter' && handleAlbumClick(track.albumId, e)}
                  class="text-[var(--color-jellyfin)] hover:underline truncate cursor-pointer"
                >
                  {track.albumName || "-"}
                </span>
              {:else}
                {track.albumName || "-"}
              {/if}
            </div>
          {/if}

          <!-- Duration -->
          <div class="text-gray-400 text-right">
            {formatDuration(track.durationMs)}
          </div>

          <!-- Download Button Placeholder -->
          {#if showDownload}
            <div class="w-12"></div>
          {/if}

          <!-- Menu Button Placeholder -->
          <div class="w-10"></div>
        </button>

        <!-- Action Buttons (separate from clickable area) -->
        <div class="hidden md:flex items-center gap-1 absolute right-4 top-1/2 -translate-y-1/2">
          {#if showDownload}
            <div onclick={(e) => e.stopPropagation()} role="none">
              <DownloadButton itemId={track.id} itemName={track.name} size="sm" />
            </div>
          {/if}

          <!-- More Options Menu -->
          <div class="relative">
            <button
              type="button"
              onclick={(e) => {
                toggleMenu(track.id, e.currentTarget, e);
              }}
              class="p-1.5 rounded text-gray-400 hover:text-white hover:bg-white/10 transition-colors"
              aria-label="More options"
            >
              <svg class="w-5 h-5" fill="currentColor" viewBox="0 0 24 24">
                <path d="M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"/>
              </svg>
            </button>
          </div>
        </div>

        <!-- Mobile View -->
        <button
          onclick={() => handleTrackClick(track, index)}
          disabled={isPlayingTrack !== null}
          class="md:hidden flex items-center gap-3 px-4 py-3 w-full disabled:opacity-50 disabled:cursor-not-allowed"
        >
          <!-- Track Number -->
          <div class="w-8 flex-shrink-0 text-center">
            {#if isPlayingTrack === track.id}
              <div class="w-4 h-4 border-2 border-[var(--color-jellyfin)] border-t-transparent rounded-full animate-spin mx-auto"></div>
            {:else}
              <span class="group-hover:hidden text-gray-400 text-sm">{index + 1}</span>
              <svg
                class="hidden group-hover:block w-4 h-4 text-white mx-auto"
                fill="currentColor"
                viewBox="0 0 24 24"
              >
                <path d="M8 5v14l11-7z" />
              </svg>
            {/if}
          </div>
          <div class="flex-1 min-w-0">
            <p
              class="text-white font-medium truncate group-hover:text-[var(--color-jellyfin)] transition-colors {currentlyPlayingId === track.id ? 'text-[var(--color-jellyfin)]' : ''}"
            >
              {#if currentlyPlayingId === track.id}
                <span class="inline-block mr-1">▶</span>
              {/if}
              {truncateMiddle(track.name, 48)}
            </p>
            <p class="text-sm text-gray-400 truncate flex flex-wrap items-center gap-1">
              {#if showArtist && showAlbum}
                {#if track.artistItems && track.artistItems.length > 0}
                  {#each track.artistItems as artist, idx}
                    <span
                      role="button"
                      tabindex="0"
                      onclick={(e) => handleArtistClick(artist.id, e)}
                      onkeydown={(e) => e.key === 'Enter' && handleArtistClick(artist.id, e)}
                      class="text-[var(--color-jellyfin)] hover:underline cursor-pointer"
                    >
                      {artist.name}
                    </span>
                    {#if idx < track.artistItems.length - 1}
                      <span>,</span>
                    {/if}
                  {/each}
                {:else}
                  {track.artists?.join(", ") || "-"}
                {/if}
                <span>•</span>
                {#if track.albumId}
                  <span
                    role="button"
                    tabindex="0"
                    onclick={(e) => handleAlbumClick(track.albumId, e)}
                    onkeydown={(e) => e.key === 'Enter' && handleAlbumClick(track.albumId, e)}
                    class="text-[var(--color-jellyfin)] hover:underline cursor-pointer"
                  >
                    {track.albumName || "-"}
                  </span>
                {:else}
                  {track.albumName || "-"}
                {/if}
              {:else if showArtist}
                {#if track.artistItems && track.artistItems.length > 0}
                  {#each track.artistItems as artist, idx}
                    <span
                      role="button"
                      tabindex="0"
                      onclick={(e) => handleArtistClick(artist.id, e)}
                      onkeydown={(e) => e.key === 'Enter' && handleArtistClick(artist.id, e)}
                      class="text-[var(--color-jellyfin)] hover:underline cursor-pointer"
                    >
                      {artist.name}
                    </span>
                    {#if idx < track.artistItems.length - 1}
                      <span>,</span>
                    {/if}
                  {/each}
                {:else}
                  {track.artists?.join(", ") || "-"}
                {/if}
              {:else if showAlbum}
                {#if track.albumId}
                  <span
                    role="button"
                    tabindex="0"
                    onclick={(e) => handleAlbumClick(track.albumId, e)}
                    onkeydown={(e) => e.key === 'Enter' && handleAlbumClick(track.albumId, e)}
                    class="text-[var(--color-jellyfin)] hover:underline cursor-pointer"
                  >
                    {track.albumName || "-"}
                  </span>
                {:else}
                  {track.albumName || "-"}
                {/if}
              {/if}
            </p>
          </div>
          <div class="text-gray-400 text-sm {showDownload ? 'mr-20' : 'mr-12'}">
            {formatDuration(track.durationMs)}
          </div>
        </button>

        <!-- Mobile Action Buttons (absolute positioned to avoid creating new line) -->
        <div class="md:hidden flex items-center gap-1 absolute right-4 top-1/2 -translate-y-1/2">
          {#if showDownload}
            <div onclick={(e) => e.stopPropagation()} role="none">
              <DownloadButton itemId={track.id} itemName={track.name} size="sm" />
            </div>
          {/if}

          <!-- Mobile More Options Menu -->
          <div class="relative">
            <button
              type="button"
              onclick={(e) => {
                toggleMenu(track.id, e.currentTarget, e);
              }}
              class="p-1.5 rounded text-gray-400 hover:text-white hover:bg-white/10 transition-colors"
              aria-label="More options"
            >
              <svg class="w-5 h-5" fill="currentColor" viewBox="0 0 24 24">
                <path d="M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"/>
              </svg>
            </button>
          </div>
        </div>
      </div>
    {/each}
  </div>
{/if}

<!-- Portal Menu (rendered at document.body to avoid overflow clipping) -->
{#if openMenuId && menuPosition}
  {@const selectedTrack = tracks.find(t => t.id === openMenuId)}
  {#if selectedTrack}
    <Portal>
      <div
        class="fixed py-1 bg-[var(--color-surface)] rounded-lg shadow-xl border border-gray-700 z-50 min-w-40"
        style="left: {menuPosition.x}px; top: {menuPosition.y}px;"
      >
        <button
          type="button"
          onclick={(e) => addToQueue(selectedTrack, "next", e)}
          class="w-full px-4 py-2 text-left text-sm text-white hover:bg-white/10 transition-colors flex items-center gap-2"
        >
          <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4" />
          </svg>
          Play Next
        </button>
        <button
          type="button"
          onclick={(e) => addToQueue(selectedTrack, "end", e)}
          class="w-full px-4 py-2 text-left text-sm text-white hover:bg-white/10 transition-colors flex items-center gap-2"
        >
          <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 10h16M4 14h16M4 18h16" />
          </svg>
          Add to Queue
        </button>
        <button
          type="button"
          onclick={(e) => {
            e.stopPropagation();
            addToPlaylistTrackId = selectedTrack.id;
            closeMenu();
          }}
          class="w-full px-4 py-2 text-left text-sm text-white hover:bg-white/10 transition-colors flex items-center gap-2"
        >
          <svg class="w-4 h-4" fill="currentColor" viewBox="0 0 24 24">
            <path d="M15 6H3v2h12V6zm0 4H3v2h12v-2zM3 16h8v-2H3v2zM17 6v8.18c-.31-.11-.65-.18-1-.18-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3V8h3V6h-5z"/>
          </svg>
          Add to Playlist
        </button>
      </div>
    </Portal>
  {/if}
{/if}

<!-- Add to Playlist Modal -->
<AddToPlaylistModal
  isOpen={addToPlaylistTrackId !== null}
  onClose={() => addToPlaylistTrackId = null}
  trackIds={addToPlaylistTrackId ? [addToPlaylistTrackId] : []}
/>

<!-- Click outside to close menu -->
<svelte:window onclick={closeMenu} />
