<!-- TRACES: UR-010 | JA-021, JA-025 | DR-037 -->
<script lang="ts">
  import { get } from "svelte/store";
  import { sessions, controllableSessions, selectedSession } from "$lib/stores";
  import { playbackMode, isTransferring, transferError } from "$lib/stores/playbackMode";
  import { playbackPosition } from "$lib/stores/player";
  import { lmsSync, isLmsSession, macForSession } from "$lib/stores/lmsSync";
  import type { Session } from "$lib/api/types";

  interface Props {
    isOpen?: boolean;
    onClose?: () => void;
    onSelectSession?: (session: Session) => void;
  }

  let { isOpen = false, onClose, onSelectSession }: Props = $props();

  // MACs currently part of any sync group, for rendering toggle state.
  const groupedMacs = $derived(new Set(($lmsSync.groups ?? []).flatMap(
    (g) => [g.masterMac, ...(g.slaveMacs ?? [])]
  )));

  // The sync master is the LMS zone we're currently controlling. Zones can only
  // be fused once we have a master to fuse them into.
  const masterMac = $derived(isLmsSession($selectedSession) ? macForSession($selectedSession) : null);

  function isZoneFused(session: Session): boolean {
    const mac = macForSession(session);
    return mac !== null && groupedMacs.has(mac);
  }

  async function handleSessionSelect(session: Session) {
    try {
      // Transfer playback to remote session, resuming at our current position
      await playbackMode.transferToRemote(session.id, get(playbackPosition));

      if (onSelectSession) {
        onSelectSession(session);
      }
      if (onClose) {
        onClose();
      }
    } catch (error) {
      console.error("Failed to select session:", error);
      // Error is already stored in playbackMode store
    }
  }

  // Toggle an LMS zone in/out of the current master's sync group. If there's no
  // master yet (we're not controlling an LMS zone), the click falls back to a
  // normal transfer so the user can start playing on a zone first.
  async function handleLmsZoneToggle(session: Session) {
    const zoneMac = macForSession(session);
    if (!zoneMac) return;

    if (!masterMac) {
      // No master yet — start playback on this zone; it becomes the master.
      await handleSessionSelect(session);
      await lmsSync.refresh();
      return;
    }

    try {
      if (isZoneFused(session)) {
        await lmsSync.decoupleZone(zoneMac);
      } else {
        await lmsSync.fuseZone(masterMac, zoneMac);
      }
    } catch (error) {
      console.error("Failed to toggle LMS zone:", error);
      // Error is surfaced via the lmsSync store
    }
  }

  async function handleTransferToLocal() {
    try {
      await playbackMode.transferToLocal();
      if (onClose) {
        onClose();
      }
    } catch (error) {
      console.error("Failed to transfer to local:", error);
      // Error is already stored in playbackMode store
    }
  }

  async function handleDisconnect() {
    try {
      await playbackMode.disconnect();
      if (onClose) {
        onClose();
      }
    } catch (error) {
      console.error("Failed to disconnect:", error);
      // Error is already stored in playbackMode store
    }
  }

  function handleClearError() {
    playbackMode.clearError();
  }

  function handleBackdropClick(event: MouseEvent) {
    if (event.target === event.currentTarget && onClose) {
      onClose();
    }
  }

  function getSessionIcon(client: string | null | undefined): string {
    const clientLower = (client ?? "").toLowerCase();
    if (clientLower.includes("tv") || clientLower.includes("roku") || clientLower.includes("android tv")) {
      return "tv";
    } else if (clientLower.includes("web") || clientLower.includes("chrome") || clientLower.includes("firefox")) {
      return "web";
    } else if (clientLower.includes("mobile") || clientLower.includes("ios") || clientLower.includes("android")) {
      return "phone";
    }
    return "device";
  }

  $effect(() => {
    if (isOpen) {
      sessions.refresh();
      lmsSync.refresh();
    }
  });
</script>

{#if isOpen}
  <!-- Backdrop -->
  <div
    class="fixed inset-0 bg-black/60 z-50 flex items-end sm:items-center justify-center p-0 sm:p-4"
    onclick={handleBackdropClick}
    onkeydown={(e) => { if (e.key === 'Escape' && onClose) onClose(); }}
    role="dialog"
    aria-modal="true"
    aria-labelledby="session-picker-title"
    tabindex="-1"
  >
    <!-- Modal -->
    <div
      class="bg-[var(--color-surface)] rounded-t-2xl sm:rounded-2xl w-full sm:max-w-md max-h-[80vh] sm:max-h-[70vh] flex flex-col shadow-2xl"
      onclick={(e) => e.stopPropagation()}
      role="none"
    >
      <!-- Header -->
      <div class="px-6 py-4 border-b border-gray-800 flex items-center justify-between">
        <h2 id="session-picker-title" class="text-lg font-semibold text-white">
          Cast to Device
        </h2>
        <button
          onclick={onClose}
          class="p-2 -m-2 text-gray-400 hover:text-white transition-colors"
          aria-label="Close"
        >
          <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
          </svg>
        </button>
      </div>

      <!-- Content -->
      <div class="flex-1 overflow-y-auto">
        {#if $sessions.isLoading && $controllableSessions.length === 0}
          <!-- Loading -->
          <div class="flex items-center justify-center py-12">
            <div class="flex flex-col items-center gap-3">
              <div class="w-8 h-8 border-4 border-[var(--color-jellyfin)] border-t-transparent rounded-full animate-spin"></div>
              <p class="text-sm text-gray-400">Searching for devices...</p>
            </div>
          </div>
        {:else if $controllableSessions.length > 0}
          <!-- Sessions list -->
          <div class="p-4 space-y-2">
            {#if $selectedSession}
              <!-- Currently connected session -->
              <div class="mb-4 p-4 rounded-lg bg-[var(--color-jellyfin)]/10 border border-[var(--color-jellyfin)]/30">
                <div class="flex items-center justify-between mb-2">
                  <span class="text-xs font-medium text-[var(--color-jellyfin)] uppercase">Connected</span>
                  <button
                    onclick={handleDisconnect}
                    class="text-xs text-gray-400 hover:text-white transition-colors"
                  >
                    Disconnect
                  </button>
                </div>
                <div class="flex items-center gap-3">
                  <div class="w-10 h-10 rounded-lg bg-[var(--color-jellyfin)]/20 flex items-center justify-center flex-shrink-0">
                    <svg class="w-5 h-5 text-[var(--color-jellyfin)]" fill="currentColor" viewBox="0 0 24 24">
                      {#if getSessionIcon($selectedSession.client) === "tv"}
                        <path d="M21 3H3c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h5v2h8v-2h5c1.1 0 1.99-.9 1.99-2L23 5c0-1.1-.9-2-2-2zm0 14H3V5h18v12z" />
                      {:else if getSessionIcon($selectedSession.client) === "web"}
                        <path d="M20 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm-5 14H4v-4h11v4zm0-5H4V9h11v4zm5 5h-4V9h4v9z" />
                      {:else if getSessionIcon($selectedSession.client) === "phone"}
                        <path d="M17 1.01L7 1c-1.1 0-2 .9-2 2v18c0 1.1.9 2 2 2h10c1.1 0 2-.9 2-2V3c0-1.1-.9-1.99-2-1.99zM17 19H7V5h10v14z" />
                      {:else}
                        <path d="M20 18c1.1 0 1.99-.9 1.99-2L22 6c0-1.1-.9-2-2-2H4c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2H0v2h24v-2h-4zM4 6h16v10H4V6z" />
                      {/if}
                    </svg>
                  </div>
                  <div class="flex-1 min-w-0">
                    <h3 class="font-medium text-white truncate">{$selectedSession.deviceName}</h3>
                    <p class="text-sm text-gray-400 truncate">{$selectedSession.client}</p>
                  </div>
                </div>
              </div>
            {/if}

            <!-- Available sessions -->
            {#each $controllableSessions as session (session.id)}
              {#if session.id !== $selectedSession?.id}
                {@const lmsZone = isLmsSession(session)}
                {@const fused = lmsZone && isZoneFused(session)}
                <button
                  onclick={() => (lmsZone ? handleLmsZoneToggle(session) : handleSessionSelect(session))}
                  disabled={$lmsSync.isBusy}
                  aria-pressed={lmsZone ? fused : undefined}
                  class="w-full p-4 rounded-lg border transition-all text-left disabled:opacity-60
                    {fused
                      ? 'border-[var(--color-jellyfin)] bg-[var(--color-jellyfin)]/10'
                      : 'border-gray-800 hover:border-[var(--color-jellyfin)]/50 hover:bg-[var(--color-jellyfin)]/5'}"
                >
                  <div class="flex items-center gap-3">
                    <div class="w-10 h-10 rounded-lg bg-gray-800 flex items-center justify-center flex-shrink-0">
                      <svg class="w-5 h-5 text-gray-400" fill="currentColor" viewBox="0 0 24 24">
                        {#if lmsZone}
                          <!-- speaker icon for LMS zones -->
                          <path d="M12 2a1 1 0 011 1v18a1 1 0 01-1 1H6a2 2 0 01-2-2V4a2 2 0 012-2h6zm0 2H6v16h6V4zm-3 9a2 2 0 110 4 2 2 0 010-4zm0-2a4 4 0 100 8 4 4 0 000-8zm0-4a1 1 0 110 2 1 1 0 010-2zm9 0h2v2h-2V7zm0 4h2v2h-2v-2z" />
                        {:else if getSessionIcon(session.client) === "tv"}
                          <path d="M21 3H3c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h5v2h8v-2h5c1.1 0 1.99-.9 1.99-2L23 5c0-1.1-.9-2-2-2zm0 14H3V5h18v12z" />
                        {:else if getSessionIcon(session.client) === "web"}
                          <path d="M20 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm-5 14H4v-4h11v4zm0-5H4V9h11v4zm5 5h-4V9h4v9z" />
                        {:else if getSessionIcon(session.client) === "phone"}
                          <path d="M17 1.01L7 1c-1.1 0-2 .9-2 2v18c0 1.1.9 2 2 2h10c1.1 0 2-.9 2-2V3c0-1.1-.9-1.99-2-1.99zM17 19H7V5h10v14z" />
                        {:else}
                          <path d="M20 18c1.1 0 1.99-.9 1.99-2L22 6c0-1.1-.9-2-2-2H4c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2H0v2h24v-2h-4zM4 6h16v10H4V6z" />
                        {/if}
                      </svg>
                    </div>
                    <div class="flex-1 min-w-0">
                      <h3 class="font-medium text-white truncate">{session.deviceName}</h3>
                      <p class="text-sm text-gray-400 truncate">
                        {#if lmsZone}
                          {fused ? "In sync group — tap to remove" : masterMac ? "Tap to add to group" : "Speaker zone"}
                        {:else}
                          {session.client}
                        {/if}
                      </p>
                      {#if session.nowPlayingItem}
                        <p class="text-xs text-gray-500 truncate mt-1">
                          Playing: {session.nowPlayingItem.name}
                        </p>
                      {/if}
                    </div>
                    {#if lmsZone}
                      <!-- Fuse toggle indicator -->
                      <div class="flex-shrink-0">
                        {#if fused}
                          <svg class="w-5 h-5 text-[var(--color-jellyfin)]" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true">
                            <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z" />
                          </svg>
                        {:else}
                          <svg class="w-5 h-5 text-gray-600" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
                            <circle cx="12" cy="12" r="9" stroke-width="2" />
                          </svg>
                        {/if}
                      </div>
                    {:else if session.playState}
                      <div class="flex-shrink-0">
                        {#if session.playState.isPaused}
                          <svg class="w-4 h-4 text-gray-500" fill="currentColor" viewBox="0 0 24 24">
                            <path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z" />
                          </svg>
                        {:else}
                          <svg class="w-4 h-4 text-[var(--color-jellyfin)]" fill="currentColor" viewBox="0 0 24 24">
                            <path d="M8 5v14l11-7z" />
                          </svg>
                        {/if}
                      </div>
                    {/if}
                  </div>
                </button>
              {/if}
            {/each}
          </div>
        {:else}
          <!-- Empty state -->
          <div class="flex flex-col items-center justify-center py-12 px-6 text-center">
            <svg class="w-16 h-16 text-gray-600 mb-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
              <path
                stroke-linecap="round"
                stroke-linejoin="round"
                stroke-width="2"
                d="M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"
              />
            </svg>
            <h3 class="text-base font-medium text-gray-400 mb-2">No Devices Found</h3>
            <p class="text-sm text-gray-500 mb-4">
              Start playing media on another Jellyfin client to cast to it from here.
            </p>
            <button
              onclick={() => sessions.refresh()}
              class="px-4 py-2 rounded-lg bg-[var(--color-jellyfin)] text-white text-sm font-medium hover:bg-[var(--color-jellyfin-hover)] transition-colors"
            >
              Refresh
            </button>
          </div>
        {/if}
      </div>

      <!-- Footer -->
      {#if $controllableSessions.length > 0}
        <div class="px-6 py-3 border-t border-gray-800">
          <!-- Play Locally Button (shown when remote session is active) -->
          {#if $selectedSession && $playbackMode.mode === "remote"}
            <button
              onclick={handleTransferToLocal}
              class="w-full mb-3 p-3 rounded-lg bg-[var(--color-jellyfin)] text-white font-medium hover:bg-[var(--color-jellyfin-hover)] transition-colors flex items-center justify-center gap-2"
              disabled={$isTransferring}
            >
              <svg class="w-5 h-5" fill="currentColor" viewBox="0 0 24 24">
                <path d="M20 18c1.1 0 1.99-.9 1.99-2L22 6c0-1.1-.9-2-2-2H4c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2H0v2h24v-2h-4zM4 6h16v10H4V6z" />
              </svg>
              Play Locally
            </button>
          {/if}

          <div class="flex items-center justify-between">
            <button
              onclick={() => sessions.refresh()}
              class="text-sm text-gray-400 hover:text-white 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 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"
                />
              </svg>
              Refresh
            </button>
            <span class="text-xs text-gray-500">
              {$controllableSessions.length} device{$controllableSessions.length !== 1 ? "s" : ""} available
            </span>
          </div>
        </div>
      {/if}

      <!-- Transfer Progress Overlay -->
      {#if $isTransferring}
        <div class="absolute inset-0 bg-black/70 flex items-center justify-center z-10 rounded-2xl">
          <div class="bg-[var(--color-surface)] p-6 rounded-lg flex flex-col items-center gap-4">
            <div class="w-10 h-10 border-4 border-[var(--color-jellyfin)] border-t-transparent rounded-full animate-spin"></div>
            <p class="text-white font-medium">Transferring playback...</p>
            <button
              onclick={() => {
                playbackMode.cancelTransfer();
                if (onClose) onClose();
              }}
              class="px-4 py-2 rounded-lg bg-gray-700 text-white text-sm font-medium hover:bg-gray-600 transition-colors"
            >
              Cancel
            </button>
          </div>
        </div>
      {/if}

      <!-- LMS sync error -->
      {#if $lmsSync.error}
        <div class="absolute bottom-0 left-0 right-0 bg-red-500/90 text-white px-6 py-3 flex items-center justify-between z-10 rounded-b-2xl">
          <div class="flex items-center gap-2">
            <svg class="w-5 h-5 flex-shrink-0" fill="currentColor" viewBox="0 0 24 24">
              <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z" />
            </svg>
            <span class="text-sm">{$lmsSync.error}</span>
          </div>
          <button
            onclick={() => lmsSync.clearError()}
            class="text-white hover:text-gray-200 transition-colors"
            aria-label="Dismiss error"
          >
            <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
              <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
            </svg>
          </button>
        </div>
      {/if}

      <!-- Error Display -->
      {#if $transferError}
        <div class="absolute bottom-0 left-0 right-0 bg-red-500/90 text-white px-6 py-3 flex items-center justify-between z-10 rounded-b-2xl">
          <div class="flex items-center gap-2">
            <svg class="w-5 h-5 flex-shrink-0" fill="currentColor" viewBox="0 0 24 24">
              <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z" />
            </svg>
            <span class="text-sm">{$transferError}</span>
          </div>
          <button
            onclick={handleClearError}
            class="text-white hover:text-gray-200 transition-colors"
            aria-label="Dismiss error"
          >
            <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
              <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
            </svg>
          </button>
        </div>
      {/if}
    </div>
  </div>
{/if}
