<script lang="ts">
  import '../app.css';
  import { page } from '$app/state';
  import { goto } from '$app/navigation';
  import { QueryClientProvider } from '@tanstack/svelte-query';
  import { queryClient } from '$lib/query/client';
  import { user } from '$lib/auth/store.svelte';
  import Shell from '$lib/components/Shell.svelte';
  import {
    registerAudioEl,
    reportTimeUpdate,
    reportDuration,
    reportStateFromAudio,
    player
  } from '$lib/player/store.svelte';
  import { useMediaSession } from '$lib/player/mediaSession.svelte';
  import { useEventsDispatcher } from '$lib/player/events.svelte';

  let { children } = $props<{ children: import('svelte').Snippet }>();
  let audioEl: HTMLAudioElement | undefined = $state();

  // Reactive guard: runs every time page.url or user.value changes.
  $effect(() => {
    const path = page.url.pathname;
    const isLogin = path === '/login';
    if (user.value === null && !isLogin) {
      const returnTo = path + page.url.search;
      goto('/login?returnTo=' + encodeURIComponent(returnTo), { replaceState: true });
    } else if (user.value !== null && isLogin) {
      goto('/', { replaceState: true });
    }
  });

  $effect(() => {
    if (audioEl) registerAudioEl(audioEl);
    return () => registerAudioEl(null);
  });

  $effect(() => {
    if (!audioEl) return;
    const src = player.current?.stream_url;
    if (src) {
      const absolute = new URL(src, window.location.origin).href;
      if (audioEl.src !== absolute) audioEl.src = src;
    } else {
      audioEl.removeAttribute('src');
      audioEl.load();
    }
  });

  $effect(() => {
    if (audioEl) audioEl.volume = player.volume;
  });

  $effect(() => {
    if (!audioEl) return;
    // "Intent to play" = loading or playing. During 'loading' the DOM hasn't
    // emitted 'playing' yet, but we still need to call play() to get there.
    const intent = player.state === 'playing' || player.state === 'loading';
    if (intent) {
      audioEl.play().catch(() => { /* interrupted / blocked — store gets the event */ });
    } else {
      audioEl.pause();
    }
  });

  useMediaSession();
  useEventsDispatcher();
</script>

<audio
  bind:this={audioEl}
  preload="metadata"
  ontimeupdate={() => audioEl && reportTimeUpdate(audioEl.currentTime)}
  onloadedmetadata={() => audioEl && reportDuration(audioEl.duration)}
  onplaying={() => reportStateFromAudio('playing')}
  onpause={() => reportStateFromAudio('paused')}
  onwaiting={() => reportStateFromAudio('waiting')}
  onended={() => reportStateFromAudio('ended')}
  onerror={() => reportStateFromAudio('error', audioEl?.error?.message)}
></audio>

<QueryClientProvider client={queryClient}>
  {#if user.value !== null && page.url.pathname !== '/login'}
    <Shell>{@render children()}</Shell>
  {:else}
    {@render children()}
  {/if}
</QueryClientProvider>
