<script lang="ts">
  import type { MediaItem, Library } from "$lib/api/types";
  import { truncateMiddle } from "$lib/utils/truncateMiddle";
  import { downloads } from "$lib/stores/downloads";
  import { formatDuration } from "$lib/utils/duration";
  import CachedImage from "$lib/components/common/CachedImage.svelte";

  interface Props {
    items: (MediaItem | Library)[];
    showProgress?: boolean;
    showDownloadStatus?: boolean;
    onItemClick?: (item: MediaItem | Library) => void;
  }

  let { items, showProgress = false, showDownloadStatus = true, onItemClick }: Props = $props();

  function getDownloadInfo(itemId: string) {
    return Object.values($downloads.downloads).find((d) => d.itemId === itemId);
  }

  function getImageTag(item: MediaItem | Library): string | undefined {
    return "primaryImageTag" in item ? (item.primaryImageTag ?? undefined) : ("imageTag" in item ? (item.imageTag ?? undefined) : undefined);
  }

  function getSubtitle(item: MediaItem | Library): string {
    if (!("type" in item)) return "";

    switch (item.type) {
      case "Audio":
        return item.artists?.join(", ") || item.albumName || "";
      case "MusicAlbum":
        return item.artistItems?.map((a) => a.name).join(", ") || "";
      case "Episode":
        return item.seriesName ? `${item.seriesName} - S${item.parentIndexNumber}E${item.indexNumber}` : "";
      case "Movie":
      case "Series":
        return item.productionYear?.toString() || "";
      default:
        return "";
    }
  }


  function getProgress(item: MediaItem | Library): number {
    if (!showProgress || !("userData" in item) || !item.userData || !("runTimeTicks" in item) || !item.runTimeTicks) {
      return 0;
    }
    return ((item.userData.playbackPositionTicks ?? 0) / item.runTimeTicks) * 100;
  }

  function getTrackNumber(item: MediaItem | Library): string {
    if ("indexNumber" in item && item.indexNumber) {
      return item.indexNumber.toString();
    }
    return "";
  }
</script>

<div class="space-y-1">
  {#each items as item, index (item.id)}
    {@const subtitle = getSubtitle(item)}
    {@const duration = "runTimeTicks" in item ? formatDuration(item.runTimeTicks) : ""}
    {@const progress = getProgress(item)}
    {@const trackNum = getTrackNumber(item)}
    {@const isPlayed = "userData" in item && item.userData?.isPlayed}
    {@const downloadInfo = getDownloadInfo(item.id)}
    {@const isDownloaded = downloadInfo?.status === "completed"}
    {@const isDownloading = downloadInfo?.status === "downloading" || downloadInfo?.status === "pending"}

    <button
      type="button"
      data-grid-index={index}
      onclick={() => onItemClick?.(item)}
      class="w-full flex items-center gap-3 p-2 rounded-lg hover:bg-[var(--color-surface)] transition-colors group"
    >
      <!-- Track number or index -->
      <span class="text-gray-500 w-6 text-right text-sm flex-shrink-0">
        {trackNum || index + 1}
      </span>

      <!-- Thumbnail -->
      <div class="w-10 h-10 rounded bg-[var(--color-surface)] flex-shrink-0 overflow-hidden relative">
        <CachedImage
          itemId={item.id}
          imageType="Primary"
          tag={getImageTag(item)}
          maxWidth={80}
          alt={item.name}
          class="w-full h-full object-cover"
        />

        <!-- Play overlay on hover -->
        <div class="absolute inset-0 bg-black/50 opacity-0 group-hover:opacity-100 transition-opacity flex items-center justify-center">
          <svg class="w-5 h-5 text-white" fill="currentColor" viewBox="0 0 24 24">
            <path d="M8 5v14l11-7z"/>
          </svg>
        </div>

        <!-- Progress bar -->
        {#if progress > 0}
          <div class="absolute bottom-0 left-0 right-0 h-0.5 bg-gray-700">
            <div class="h-full bg-[var(--color-jellyfin)]" style="width: {progress}%"></div>
          </div>
        {/if}
      </div>

      <!-- Title & Subtitle -->
      <div class="flex-1 min-w-0 text-left">
        <p class="text-sm font-medium text-white truncate group-hover:text-[var(--color-jellyfin)] transition-colors">
          {truncateMiddle(item.name, 56)}
        </p>
        {#if subtitle}
          <p class="text-xs text-gray-400 truncate">{subtitle}</p>
        {/if}
      </div>

      <!-- Download indicator -->
      {#if showDownloadStatus && (isDownloaded || isDownloading)}
        {#if isDownloaded}
          <span title="Downloaded">
            <svg class="w-4 h-4 text-green-500 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2" aria-label="Downloaded">
              <path stroke-linecap="round" stroke-linejoin="round" d="M12 4v12m0 0l-4-4m4 4l4-4" />
            </svg>
          </span>
        {:else if isDownloading}
          <div class="w-4 h-4 relative flex-shrink-0" title="Downloading...">
            <svg class="w-4 h-4 -rotate-90" viewBox="0 0 24 24">
              <circle cx="12" cy="12" r="10" fill="none" stroke="currentColor" stroke-width="2" opacity="0.3" class="text-blue-500" />
              <circle
                cx="12" cy="12" r="10" fill="none" stroke="currentColor" stroke-width="2"
                stroke-dasharray={2 * Math.PI * 10}
                stroke-dashoffset={2 * Math.PI * 10 * (1 - (downloadInfo?.progress || 0))}
                stroke-linecap="round" class="text-blue-500 transition-all duration-300"
              />
            </svg>
          </div>
        {/if}
      {/if}

      <!-- Played indicator -->
      {#if isPlayed}
        <svg class="w-4 h-4 text-[var(--color-jellyfin)] flex-shrink-0" fill="currentColor" viewBox="0 0 24 24">
          <path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/>
        </svg>
      {/if}

      <!-- Duration -->
      {#if duration}
        <span class="text-xs text-gray-400 flex-shrink-0">{duration}</span>
      {/if}
    </button>
  {/each}
</div>
