<!--
  The one and only episode surface (ux-flows §5B.1) — so it carries everything
  an episode can do, not just Play. A bare Episode page used to exist alongside
  it with a *different* set of affordances (download, breadcrumbs, cast), which
  meant opening an episode from Continue Watching silently lost them.

  TRACES: UR-048, UR-058 | DR-061, DR-062, DR-142
-->
<script lang="ts">
  import { goto } from "$app/navigation";
  import { formatDuration } from "$lib/utils/duration";
  import { truncateMiddle } from "$lib/utils/truncateMiddle";
  import type { MediaItem } from "$lib/api/types";
  import CachedImage from "$lib/components/common/CachedImage.svelte";
  import FavoriteButton from "$lib/components/FavoriteButton.svelte";
  import VideoDownloadButton from "./VideoDownloadButton.svelte";
  import WatchedToggleButton from "./WatchedToggleButton.svelte";
  import CastSection from "./CastSection.svelte";
  import GenreTags from "./GenreTags.svelte";
  import RelatedItemsSection from "./RelatedItemsSection.svelte";
  import { favoriteOverrides, resolveIsFavorite } from "$lib/stores/favorites";
  import { seasonAnchorId } from "./seriesNavigation";
  import {
    isCurrentEpisode as isSameEpisode,
    adjacentEpisodes as computeAdjacent,
    stripCardLabel,
  } from "./episodeStrip";

  interface Props {
    episode: MediaItem;
    /**
     * The parent series. `null` only for an episode that carries no `seriesId`
     * (a deep link into a stale cache) — the view still renders, minus the
     * affordances that need series context.
     */
    series?: MediaItem | null;
    allEpisodes?: MediaItem[];
    onBack?: () => void;
  }

  let { episode, series = null, allEpisodes = [], onBack }: Props = $props();

  // Pure logic lives in ./episodeStrip.ts (unit-tested). Wrap for local use.
  function isCurrentEpisode(ep: MediaItem): boolean {
    return isSameEpisode(ep, episode);
  }

  const adjacentEpisodes = $derived(() => computeAdjacent(episode, allEpisodes));

  // A strip of exactly one card is the current episode talking to itself — the
  // spec wants the *next* episodes, so with no siblings there is nothing to show.
  const hasEpisodeStrip = $derived(adjacentEpisodes().length > 1);

  // Compute best backdrop source (no fetch, pure derivation)
  const backdropSource = $derived.by(() => {
    if (episode.backdropImageTags?.[0]) {
      return {
        itemId: episode.id,
        imageType: "Backdrop" as const,
        tag: episode.backdropImageTags[0],
      };
    }
    if (episode.imageId) {
      return { itemId: episode.id, imageType: "Primary" as const, tag: episode.imageId };
    }
    if (series?.backdropImageTags?.[0]) {
      return {
        itemId: series.id,
        imageType: "Backdrop" as const,
        tag: series.backdropImageTags[0],
      };
    }
    return null;
  });

  // Cast and genres are the episode's own when the server sent them, else the
  // series' — a list-level episode fetch often carries neither, and an empty
  // Cast row on an episode of a show with a known cast reads as broken.
  const people = $derived(episode.people?.length ? episode.people : (series?.people ?? []));
  const genres = $derived(episode.genres?.length ? episode.genres : (series?.genres ?? []));

  // "More Like This" on an episode means similar *shows* (UR-048), so it keys
  // off the series rather than the episode.
  const seriesName = $derived(series?.name ?? episode.seriesName ?? null);
  const seriesHref = $derived(series ? `/library/${series.id}` : null);
  const seasonHref = $derived(
    series && episode.parentIndexNumber != null
      ? `/library/${series.id}#${seasonAnchorId(episode.parentIndexNumber)}`
      : null,
  );

  function getProgress(ep: MediaItem): number {
    if (!ep.userData || !ep.durationMs) {
      return 0;
    }
    return ((ep.userData.playbackPositionMs ?? 0) / ep.durationMs) * 100;
  }

  function handlePlay() {
    goto(`/player/${episode.id}`);
  }

  function handleEpisodeClick(ep: MediaItem) {
    if (!series) return;
    goto(`/library/${series.id}?episode=${ep.id}`);
  }

  const episodeLabel = $derived(`S${episode.parentIndexNumber || 1}E${episode.indexNumber || 1}`);
  const duration = $derived(formatDuration(episode.durationMs, "h m"));
  const progress = $derived(getProgress(episode));
</script>

<div class="space-y-8">
  <!-- Hero section -->
  <div class="relative h-[450px] rounded-xl overflow-hidden">
    {#if backdropSource}
      <CachedImage
        itemId={backdropSource.itemId}
        imageType={backdropSource.imageType}
        tag={backdropSource.tag}
        maxWidth={1920}
        alt={episode.name}
        class="absolute inset-0 w-full h-full object-cover"
      />
    {:else}
      <div
        class="absolute inset-0 bg-gradient-to-br from-[var(--color-jellyfin)] to-purple-900"
      ></div>
    {/if}

    <!-- Gradient overlay -->
    <div class="absolute inset-0 bg-gradient-to-r from-black/90 via-black/60 to-transparent"></div>
    <div
      class="absolute inset-0 bg-gradient-to-t from-black/80 via-transparent to-transparent"
    ></div>

    <!-- Back button -->
    {#if onBack}
      <button
        onclick={onBack}
        class="absolute top-4 left-4 p-2 rounded-full bg-black/50 hover:bg-black/70 transition-colors"
        title="Back to series"
      >
        <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
          <path
            stroke-linecap="round"
            stroke-linejoin="round"
            stroke-width="2"
            d="M15 19l-7-7 7-7"
          />
        </svg>
      </button>
    {/if}

    <!-- Content -->
    <div class="relative h-full flex flex-col justify-end p-8 max-w-3xl">
      <div class="space-y-4">
        <!-- Series name — a link, so the episode page is a navigable hub
             rather than a dead end (UR-058). -->
        {#if seriesName}
          <p class="text-lg">
            {#if seriesHref}
              <a
                href={seriesHref}
                class="text-gray-300 hover:text-white hover:underline transition-colors"
              >
                {seriesName}
              </a>
            {:else}
              <span class="text-gray-300">{seriesName}</span>
            {/if}
          </p>
        {/if}

        <!-- Episode title -->
        <h1 class="text-4xl font-bold text-white drop-shadow-lg">
          {truncateMiddle(episode.name, 64)}
        </h1>

        <!-- Metadata -->
        <div class="flex items-center gap-4 text-sm text-gray-200">
          <!-- The badge links to the season's place in the series list —
               seasons have no page of their own (DR-103). -->
          {#if seasonHref}
            <a
              href={seasonHref}
              class="px-2 py-1 bg-[var(--color-jellyfin)] rounded font-semibold hover:brightness-110 transition-all"
            >
              {episodeLabel}
            </a>
          {:else}
            <span class="px-2 py-1 bg-[var(--color-jellyfin)] rounded font-semibold">
              {episodeLabel}
            </span>
          {/if}
          {#if duration}
            <span>{duration}</span>
          {/if}
          {#if episode.communityRating}
            <span class="flex items-center gap-1">
              <svg class="w-4 h-4 text-yellow-400" fill="currentColor" viewBox="0 0 24 24">
                <path
                  d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"
                />
              </svg>
              {episode.communityRating.toFixed(1)}
            </span>
          {/if}
          {#if episode.userData?.isPlayed}
            <span class="flex items-center gap-1 text-[var(--color-jellyfin)]">
              <svg class="w-4 h-4" 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>
              Watched
            </span>
          {/if}
        </div>

        <!-- Overview -->
        {#if episode.overview}
          <p class="text-gray-200 line-clamp-3 text-lg leading-relaxed max-w-2xl">
            {episode.overview}
          </p>
        {/if}

        <!-- Progress bar if in progress -->
        {#if progress > 0 && progress < 95}
          <div class="w-64">
            <div class="h-1 bg-gray-700 rounded-full overflow-hidden">
              <div class="h-full bg-[var(--color-jellyfin)]" style="width: {progress}%"></div>
            </div>
            <p class="text-xs text-gray-400 mt-1">
              {Math.round(progress)}% watched
            </p>
          </div>
        {/if}

        <!-- Play / Download / Favourite — the full hero action row of
             ux-flows §5B.2. TRACES: UR-058, UR-068 | DR-119, DR-142 -->
        <div class="pt-2 flex items-center gap-3">
          <button
            onclick={handlePlay}
            class="px-8 py-3 bg-white text-black hover:bg-white/90 rounded-lg font-semibold text-lg flex items-center gap-2 transition-colors"
          >
            <svg class="w-6 h-6" fill="currentColor" viewBox="0 0 24 24">
              <path d="M8 5v14l11-7z" />
            </svg>
            {progress > 0 && progress < 95 ? "Resume" : "Play"}
          </button>
          <VideoDownloadButton
            itemId={episode.id}
            itemName={episode.name}
            isMovie={false}
            seriesName={seriesName ?? undefined}
            seasonName={episode.seasonName ?? undefined}
            seasonNumber={episode.parentIndexNumber ?? undefined}
            episodeNumber={episode.indexNumber ?? undefined}
            size="lg"
          />
          <WatchedToggleButton
            itemId={episode.id}
            watched={episode.userData?.isPlayed ?? false}
            scope="episode"
            size="lg"
          />
          <FavoriteButton
            itemId={episode.id}
            isFavorite={resolveIsFavorite(episode, $favoriteOverrides)}
            size="lg"
          />
        </div>
      </div>
    </div>
  </div>

  <!-- Adjacent episodes. Nothing may be inserted between the hero and this
       strip — continuation content comes before discovery content
       (ux-flows §5B.2). TRACES: UR-048 | DR-061, DR-062 -->
  {#if hasEpisodeStrip}
    <div class="space-y-4">
      <h2 class="text-xl font-semibold text-white">More Episodes</h2>

      <div
        class="flex gap-4 overflow-x-auto pb-4 scrollbar-thin scrollbar-thumb-gray-700 scrollbar-track-transparent"
      >
        {#each adjacentEpisodes() as ep (ep.id)}
          {@const isCurrent = isCurrentEpisode(ep)}
          {@const epProgress = getProgress(ep)}
          <button
            onclick={() => !isCurrent && handleEpisodeClick(ep)}
            class="flex-shrink-0 w-64 text-left group/card {isCurrent
              ? 'ring-2 ring-yellow-400 rounded-lg'
              : ''}"
            disabled={isCurrent}
          >
            <!-- Thumbnail -->
            <div class="relative aspect-video rounded-lg overflow-hidden bg-[var(--color-surface)]">
              <CachedImage
                itemId={ep.id}
                imageType="Primary"
                tag={ep.imageId}
                maxWidth={400}
                alt={ep.name}
                class="w-full h-full object-cover transition-transform {isCurrent
                  ? ''
                  : 'group-hover/card:scale-105'}"
              />

              <!-- Hover overlay -->
              {#if !isCurrent}
                <div
                  class="absolute inset-0 bg-black/0 group-hover/card:bg-black/30 transition-colors flex items-center justify-center"
                >
                  <div class="opacity-0 group-hover/card:opacity-100 transition-opacity">
                    <div
                      class="w-12 h-12 rounded-full bg-[var(--color-jellyfin)] flex items-center justify-center"
                    >
                      <svg class="w-6 h-6 text-white ml-1" fill="currentColor" viewBox="0 0 24 24">
                        <path d="M8 5v14l11-7z" />
                      </svg>
                    </div>
                  </div>
                </div>
              {/if}

              <!-- Now Playing indicator -->
              {#if isCurrent}
                <div
                  class="absolute top-2 left-2 px-2 py-1 bg-yellow-400 text-black rounded text-xs font-semibold"
                >
                  Current
                </div>
              {/if}

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

              <!-- Played indicator -->
              {#if ep.userData?.isPlayed}
                <div class="absolute top-2 right-2">
                  <svg
                    class="w-5 h-5 text-[var(--color-jellyfin)]"
                    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>
                </div>
              {/if}
            </div>

            <!-- Episode info -->
            <div class="mt-2 space-y-1">
              <div class="flex items-center gap-2">
                <span class="text-[var(--color-jellyfin)] text-sm font-semibold whitespace-nowrap">
                  {stripCardLabel(ep, episode)}
                </span>
                <p
                  class="text-white font-medium truncate {isCurrent
                    ? 'text-yellow-400'
                    : 'group-hover/card:text-[var(--color-jellyfin)]'} transition-colors"
                >
                  {ep.name}
                </p>
              </div>
              {#if ep.overview}
                <p class="text-gray-400 text-sm line-clamp-2">
                  {ep.overview}
                </p>
              {/if}
            </div>
          </button>
        {/each}
      </div>
    </div>
  {/if}

  <!-- Discovery content, strictly below the episode strip (ux-flows §5B.2:
       hero → strip → cast → similar). TRACES: UR-048 | DR-062, DR-142 -->
  {#if genres.length}
    <GenreTags {genres} maxShow={6} itemKind="episode" />
  {/if}

  {#if people.length}
    <CastSection {people} />
  {/if}

  <!-- "More Like This" on an episode means similar shows, so it keys off the
       series. Skipped for a series-less episode, which has nothing to match on. -->
  {#if series && (series.genres?.length || series.people?.length)}
    <RelatedItemsSection
      currentItemId={series.id}
      itemKind="series"
      genres={series.genres ?? undefined}
      people={series.people ?? undefined}
      limit={12}
    />
  {/if}
</div>
