import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest';
import { render, screen, within } from '@testing-library/svelte';
import { readable } from 'svelte/store';
import { emptyLikesMock } from '../test-utils/mocks/likes';
import type { Playlist } from '$lib/api/types';

// Mock all the queries the home page constructs.
vi.mock('$lib/api/home', () => ({
  createHomeQuery: () =>
    readable({
      data: {
        recently_added_albums: [],
        most_played_tracks: [],
        rediscover_albums: [],
        rediscover_artists: [],
        last_played_artists: [],
        you_might_like_albums: [],
        you_might_like_artists: []
      },
      isPending: false,
      isError: false,
      refetch: vi.fn()
    })
}));

vi.mock('$lib/api/playlists', () => ({
  createPlaylistsQuery: vi.fn()
}));

vi.mock('$lib/api/me', () => ({
  createSystemPlaylistsStatusQuery: vi.fn()
}));

// LikeButton imports — needed because the home renders cards that may use it.
vi.mock('$lib/api/likes', () => emptyLikesMock());

import Page from './+page.svelte';
import { createPlaylistsQuery } from '$lib/api/playlists';
import { createSystemPlaylistsStatusQuery } from '$lib/api/me';

const emptyPlaylistsResponse = { owned: [], public: [] };

beforeEach(() => {
  (createPlaylistsQuery as unknown as ReturnType<typeof vi.fn>).mockImplementation(() =>
    readable({ data: emptyPlaylistsResponse, isPending: false, isError: false })
  );
  (createSystemPlaylistsStatusQuery as unknown as ReturnType<typeof vi.fn>).mockReturnValue(
    readable({
      data: { in_flight: false, last_run_at: null, last_error: null },
      isPending: false,
      isError: false
    })
  );
});

afterEach(() => vi.clearAllMocks());

describe('home Playlists section', () => {
  test('renders 5 placeholder cards when no playlists exist', () => {
    // For-You + Discover in the Playlists row, plus 3 in the dedicated
    // Songs-like row (#1491) = 5 placeholders total.
    render(Page);
    const placeholders = screen.queryAllByTestId('playlist-placeholder-card');
    expect(placeholders).toHaveLength(5);
  });

  test('building status sets variant=building on placeholders', () => {
    (createSystemPlaylistsStatusQuery as unknown as ReturnType<typeof vi.fn>).mockReturnValue(
      readable({
        data: { in_flight: true, last_run_at: null, last_error: null },
        isPending: false,
        isError: false
      })
    );
    const { container } = render(Page);
    const buildingPlaceholders = container.querySelectorAll('[data-variant="building"]');
    expect(buildingPlaceholders.length).toBeGreaterThan(0);
  });

  test('renders For-You playlist + 3 placeholders when only for_you exists', () => {
    const forYou: Playlist = {
      id: 'fy',
      user_id: 'u1',
      owner_username: 'u1',
      name: 'For You',
      description: '',
      is_public: false,
      kind: 'system',
      system_variant: 'for_you',
      refreshable: false,
      seed_artist_id: null,
      cover_url: '',
      track_count: 25,
      duration_sec: 1500,
      created_at: '2026-05-04T00:00:00Z',
      updated_at: '2026-05-04T00:00:00Z'
    };
    (createPlaylistsQuery as unknown as ReturnType<typeof vi.fn>).mockImplementation(
      (kind?: string) =>
        kind === 'system'
          ? readable({
              data: { owned: [forYou], public: [] },
              isPending: false,
              isError: false
            })
          : readable({ data: emptyPlaylistsResponse, isPending: false, isError: false })
    );
    render(Page);
    expect(screen.getByText('For You')).toBeInTheDocument();
    const placeholders = screen.queryAllByTestId('playlist-placeholder-card');
    // 1 Discover placeholder (Playlists row) + 3 Songs-like placeholders
    // (dedicated row) = 4 alongside the real For-You tile.
    expect(placeholders).toHaveLength(4);
  });

  test('dedicated Songs-like row shows every generated mix, uncapped and out of Playlists', () => {
    const makeSongsLike = (id: string, name: string): Playlist => ({
      id,
      user_id: 'u1',
      owner_username: 'u1',
      name,
      description: '',
      is_public: false,
      kind: 'system',
      system_variant: 'songs_like_artist',
      refreshable: false,
      seed_artist_id: 'a1',
      cover_url: '',
      track_count: 25,
      duration_sec: 1500,
      created_at: '2026-05-04T00:00:00Z',
      updated_at: '2026-05-04T00:00:00Z'
    });
    // Six generated mixes — the old carousel capped at 3; the dedicated row shows all.
    const owned = Array.from({ length: 6 }, (_, i) => makeSongsLike(`sl${i}`, `Songs like ${i}`));
    (createPlaylistsQuery as unknown as ReturnType<typeof vi.fn>).mockImplementation(
      (kind?: string) =>
        kind === 'system'
          ? readable({ data: { owned, public: [] }, isPending: false, isError: false })
          : readable({ data: emptyPlaylistsResponse, isPending: false, isError: false })
    );
    const { container } = render(Page);

    for (let i = 0; i < 6; i++) {
      expect(screen.getByText(`Songs like ${i}`)).toBeInTheDocument();
    }
    // The mixes live in the Songs-like row, not the Playlists carousel.
    const playlistsSection = container.querySelector('[aria-label="Playlists"]') as HTMLElement;
    expect(within(playlistsSection).queryByText('Songs like 0')).toBeNull();
    const songsSection = container.querySelector('[aria-label="Songs like"]') as HTMLElement;
    expect(within(songsSection).getByText('Songs like 0')).toBeInTheDocument();
    // No placeholders once real mixes exist.
    expect(within(songsSection).queryByTestId('playlist-placeholder-card')).toBeNull();
  });

  test('renders secondary system kinds (deep_cuts / new_for_you) in the Playlists row', () => {
    // Operator backflow 2026-06-01: web Home surfaces the 5 secondary
    // system kinds when generated. No placeholders for them — they
    // depend on library shape, so missing means "not enough data."
    const makePlaylist = (id: string, variant: string, name: string): Playlist => ({
      id,
      user_id: 'u1',
      owner_username: 'u1',
      name,
      description: '',
      is_public: false,
      kind: 'system',
      system_variant: variant,
      refreshable: variant !== 'songs_like_artist',
      seed_artist_id: null,
      cover_url: '',
      track_count: 25,
      duration_sec: 1500,
      created_at: '2026-05-04T00:00:00Z',
      updated_at: '2026-05-04T00:00:00Z'
    });
    const owned = [
      makePlaylist('fy',   'for_you',     'For You'),
      makePlaylist('dc',   'deep_cuts',   'Deep cuts'),
      makePlaylist('nfy',  'new_for_you', 'New for you')
    ];
    (createPlaylistsQuery as unknown as ReturnType<typeof vi.fn>).mockImplementation(
      (kind?: string) =>
        kind === 'system'
          ? readable({ data: { owned, public: [] }, isPending: false, isError: false })
          : readable({ data: emptyPlaylistsResponse, isPending: false, isError: false })
    );
    render(Page);
    expect(screen.getByText('For You')).toBeInTheDocument();
    expect(screen.getByText('Deep cuts')).toBeInTheDocument();
    expect(screen.getByText('New for you')).toBeInTheDocument();
  });
});
