<script lang="ts">
  import { pageTitle } from '$lib/branding';
  import { createHomeQuery } from '$lib/api/home';
  import HorizontalScrollRow from '$lib/components/HorizontalScrollRow.svelte';
  import AlbumCard from '$lib/components/AlbumCard.svelte';
  import ArtistCard from '$lib/components/ArtistCard.svelte';
  import CompactTrackCard from '$lib/components/CompactTrackCard.svelte';
  import ApiErrorBanner from '$lib/components/ApiErrorBanner.svelte';
  import { useDelayed } from '$lib/utils/useDelayed.svelte';
  import PlaylistCard from '$lib/components/PlaylistCard.svelte';
  import PlaylistPlaceholderCard from '$lib/components/PlaylistPlaceholderCard.svelte';
  import { createPlaylistsQuery } from '$lib/api/playlists';
  import { createSystemPlaylistsStatusQuery } from '$lib/api/me';
  import type { Playlist } from '$lib/api/types';

  const queryStore = createHomeQuery();
  const query = $derived($queryStore);
  const data = $derived(query.data);

  const showSkeleton = useDelayed(() => query.isPending);

  // Each "Most played" row gets 25 of the 75 tracks (server returns up
  // to 75; rows 0/1/2 slice [0..25), [25..50), [50..75)).
  function chunk<T>(items: T[], size: number): T[][] {
    const out: T[][] = [];
    for (let i = 0; i < items.length; i += size) out.push(items.slice(i, i + size));
    return out;
  }

  const systemPlaylistsStore = $derived(createPlaylistsQuery('system'));
  const userPlaylistsStore   = $derived(createPlaylistsQuery('user'));
  const systemStatusStore    = $derived(createSystemPlaylistsStatusQuery());

  const systemPlaylistsQ = $derived($systemPlaylistsStore);
  const userPlaylistsQ   = $derived($userPlaylistsStore);
  const systemStatusQ    = $derived($systemStatusStore);

  const forYouPlaylist = $derived(
    (systemPlaylistsQ.data?.owned ?? []).find((p) => p.system_variant === 'for_you') ?? null
  );

  const discoverPlaylist = $derived(
    (systemPlaylistsQ.data?.owned ?? []).find((p) => p.system_variant === 'discover') ?? null
  );

  // Songs-like mixes get their own dedicated row (#1491) — no longer
  // capped to 3 carousel slots, so take all the server generated.
  const songsLikePlaylists = $derived(
    (systemPlaylistsQ.data?.owned ?? [])
      .filter((p) => p.system_variant === 'songs_like_artist')
  );

  // Secondary system kinds the server generates that don't get pinned
  // to fixed Home slots: surfaced after the Songs-like slots when they
  // exist, in server-registry order (internal/playlists/system.go).
  // No placeholders for these — they depend on library shape (Deep
  // cuts needs deep albums, On this day needs prior history, etc.) so
  // a missing one means "not enough data," not "still building."
  // Mirrors Android's SECONDARY_SYSTEM_VARIANTS (HomeScreen.kt). Operator
  // request 2026-06-01 for web parity.
  const SECONDARY_SYSTEM_VARIANTS = [
    'deep_cuts',
    'rediscover',
    'new_for_you',
    'on_this_day',
    'first_listens'
  ] as const;

  const secondarySystemPlaylists = $derived(
    SECONDARY_SYSTEM_VARIANTS
      .map((variant) =>
        (systemPlaylistsQ.data?.owned ?? []).find((p) => p.system_variant === variant)
      )
      .filter((p): p is Playlist => p != null)
  );

  const userPlaylists = $derived(userPlaylistsQ.data?.owned ?? []);

  type PlaceholderVariant = 'building' | 'failed' | 'pending' | 'seed-needed';
  function placeholderVariant(slot: 'for-you' | 'discover' | 'songs-like'): PlaceholderVariant {
    const s = systemStatusQ.data;
    if (!s) return 'pending';
    if (s.in_flight) return 'building';
    if (s.last_error) return 'failed';
    if (slot === 'songs-like' && s.last_run_at) return 'seed-needed';
    return 'pending';
  }

  type PlaylistRowItem =
    | { kind: 'real'; playlist: Playlist }
    | { kind: 'placeholder'; label: string; variant: PlaceholderVariant };

  const playlistsRow = $derived.by((): PlaylistRowItem[] => {
    const out: PlaylistRowItem[] = [];

    // Slot 1: For-You (real or placeholder).
    if (forYouPlaylist) {
      out.push({ kind: 'real', playlist: forYouPlaylist });
    } else {
      out.push({ kind: 'placeholder', label: 'For You', variant: placeholderVariant('for-you') });
    }

    // Slot 2: Discover (real or placeholder). Server emits this with
    // system_variant='discover' once the recommendation engine has
    // eligible tracks.
    if (discoverPlaylist) {
      out.push({ kind: 'real', playlist: discoverPlaylist });
    } else {
      out.push({ kind: 'placeholder', label: 'Discover', variant: placeholderVariant('discover') });
    }

    // Songs-like moved to its own dedicated row below (#1491).

    // Secondary system kinds in server-registry order, when generated.
    for (const p of secondarySystemPlaylists) {
      out.push({ kind: 'real', playlist: p });
    }

    // User playlists trail (server returns most-recently-updated first).
    for (const p of userPlaylists) {
      out.push({ kind: 'real', playlist: p });
    }

    return out;
  });

  // Dedicated Songs-like row (#1491): every generated "Songs like {artist}"
  // mix — the best-performing surface, promoted out of the Playlists
  // carousel to show a wider spread. Shows a few placeholders while the
  // mixes haven't generated yet (building / seed-needed).
  const SONGS_LIKE_PLACEHOLDER_SLOTS = 3;
  const songsLikeRow = $derived.by((): PlaylistRowItem[] => {
    if (songsLikePlaylists.length > 0) {
      return songsLikePlaylists.map((playlist) => ({ kind: 'real', playlist }) as PlaylistRowItem);
    }
    return Array.from(
      { length: SONGS_LIKE_PLACEHOLDER_SLOTS },
      (): PlaylistRowItem => ({
        kind: 'placeholder',
        label: 'Songs like…',
        variant: placeholderVariant('songs-like')
      })
    );
  });
</script>

<svelte:head><title>{pageTitle('Home')}</title></svelte:head>

<div class="space-y-8">
  <!-- Playlists: For-You + Songs-like + user playlists, single horizontal row -->
  <section class="space-y-3">
    <HorizontalScrollRow
      rows={[playlistsRow]}
      title="Playlists"
      ariaLabel="Playlists"
    >
      {#snippet item(rowItem: PlaylistRowItem)}
        <!-- Playlists at the page anchor: largest of the carousels.
             Sized so a typical viewport shows ~5-6 across instead
             of cramming 8-9. -->
        <div class="w-56">
          {#if rowItem.kind === 'real'}
            <PlaylistCard playlist={rowItem.playlist} />
          {:else}
            <PlaylistPlaceholderCard label={rowItem.label} variant={rowItem.variant} />
          {/if}
        </div>
      {/snippet}
    </HorizontalScrollRow>
  </section>

  <!-- Songs like…: the best-performing surface, its own row (#1491).
       Depends on the system-playlists query (same as Playlists above), so
       it sits outside the home-sections {#if data} block. -->
  <section class="space-y-3">
    <HorizontalScrollRow
      rows={[songsLikeRow]}
      title="Songs like…"
      ariaLabel="Songs like"
    >
      {#snippet item(rowItem: PlaylistRowItem)}
        <div class="w-56">
          {#if rowItem.kind === 'real'}
            <PlaylistCard playlist={rowItem.playlist} />
          {:else}
            <PlaylistPlaceholderCard label={rowItem.label} variant={rowItem.variant} />
          {/if}
        </div>
      {/snippet}
    </HorizontalScrollRow>
  </section>

  {#if query.isError}
    <ApiErrorBanner error={query.error} onRetry={query.refetch} />
  {:else if showSkeleton.value && !data}
    <p class="text-text-secondary">Loading…</p>
  {:else if data}
    <!-- You might like: taste-predicted in-library albums + artists the user
         doesn't actively spin (server section, daily-built, cold-start gated).
         Sits directly under the system playlists row. Two scrollers like
         Rediscover (square album vs circular artist cards). -->
    <section class="space-y-3">
      {#if data.you_might_like_albums.length === 0 && data.you_might_like_artists.length === 0}
        <header>
          <h2 class="font-display text-2xl font-medium text-text-primary">You might like</h2>
        </header>
        <p class="text-text-secondary">We're still learning your taste — keep listening and picks you might like will show up here.</p>
      {:else}
        {#if data.you_might_like_albums.length > 0}
          <HorizontalScrollRow
            rows={[data.you_might_like_albums]}
            title="You might like"
            ariaLabel="You might like albums"
          >
            {#snippet item(album: import('$lib/api/types').AlbumRef)}
              <div class="w-40"><AlbumCard {album} /></div>
            {/snippet}
          </HorizontalScrollRow>
        {/if}
        {#if data.you_might_like_artists.length > 0}
          <HorizontalScrollRow
            rows={[data.you_might_like_artists]}
            title={data.you_might_like_albums.length === 0 ? 'You might like' : undefined}
            ariaLabel="You might like artists"
          >
            {#snippet item(artist: import('$lib/api/types').ArtistRef)}
              <div class="w-36"><ArtistCard {artist} /></div>
            {/snippet}
          </HorizontalScrollRow>
        {/if}
      {/if}
    </section>

    <!-- Recently added: 50 albums in 2 rows of 25, scrolling together -->
    <section class="space-y-3">
      {#if data.recently_added_albums.length === 0}
        <header>
          <h2 class="font-display text-2xl font-medium text-text-primary">Recently added</h2>
        </header>
        <p class="text-text-secondary">Nothing added yet. Scan a folder via the server's config.</p>
      {:else}
        <HorizontalScrollRow
          rows={chunk(data.recently_added_albums, 25)}
          title="Recently added"
          ariaLabel="Recently added"
        >
          {#snippet item(album: import('$lib/api/types').AlbumRef)}
            <div class="w-48"><AlbumCard {album} /></div>
          {/snippet}
        </HorizontalScrollRow>
      {/if}
    </section>

    <!-- Rediscover: albums + artists. Kept as two scrollers because the
         card types differ (square vs circular); coupling them in one
         scroller would interleave shapes awkwardly. -->
    <section class="space-y-3">
      {#if data.rediscover_albums.length === 0 && data.rediscover_artists.length === 0}
        <header>
          <h2 class="font-display text-2xl font-medium text-text-primary">Rediscover</h2>
        </header>
        <p class="text-text-secondary">No forgotten favourites yet. Like some albums or artists to fill this in.</p>
      {:else}
        {#if data.rediscover_albums.length > 0}
          <HorizontalScrollRow
            rows={[data.rediscover_albums]}
            title="Rediscover"
            ariaLabel="Rediscover albums"
          >
            {#snippet item(album: import('$lib/api/types').AlbumRef)}
              <!-- Rediscover sits below Recently Added in the size
                   hierarchy. w-40 keeps it readable without competing
                   with the freshest content above. -->
              <div class="w-40"><AlbumCard {album} /></div>
            {/snippet}
          </HorizontalScrollRow>
        {/if}
        {#if data.rediscover_artists.length > 0}
          <HorizontalScrollRow
            rows={[data.rediscover_artists]}
            title={data.rediscover_albums.length === 0 ? 'Rediscover' : undefined}
            ariaLabel="Rediscover artists"
          >
            {#snippet item(artist: import('$lib/api/types').ArtistRef)}
              <div class="w-36"><ArtistCard {artist} /></div>
            {/snippet}
          </HorizontalScrollRow>
        {/if}
      {/if}
    </section>

    <!-- Most played: 75 tracks in 3 rows of 25, scrolling together -->
    <section class="space-y-3">
      {#if data.most_played_tracks.length === 0}
        <header>
          <h2 class="font-display text-2xl font-medium text-text-primary">Most played</h2>
        </header>
        <p class="text-text-secondary">No plays to draw from. Listen to something.</p>
      {:else}
        <HorizontalScrollRow
          rows={chunk(data.most_played_tracks, 25)}
          title="Most played"
          ariaLabel="Most played"
        >
          {#snippet item(track: import('$lib/api/types').TrackRef, globalIdx: number)}
            <CompactTrackCard
              {track}
              sectionTracks={data.most_played_tracks}
              index={globalIdx}
            />
          {/snippet}
        </HorizontalScrollRow>
      {/if}
    </section>

    <!-- Last played artists -->
    <section class="space-y-3">
      {#if data.last_played_artists.length === 0}
        <header>
          <h2 class="font-display text-2xl font-medium text-text-primary">Last played</h2>
        </header>
        <p class="text-text-secondary">No recent plays.</p>
      {:else}
        <HorizontalScrollRow
          rows={[data.last_played_artists]}
          title="Last played"
          ariaLabel="Last played artists"
        >
          {#snippet item(artist: import('$lib/api/types').ArtistRef)}
            <div class="w-36"><ArtistCard {artist} /></div>
          {/snippet}
        </HorizontalScrollRow>
      {/if}
    </section>
  {/if}
</div>
