import { describe, expect, test, beforeEach } from 'vitest';
import type { TrackRef } from '$lib/api/types';
import { makeTrack } from '$test-utils/fixtures/track';
import {
  selection, toggleOne, selectRange, clearSelection
} from './store.svelte';

function tracks(): TrackRef[] {
  return [
    makeTrack({ id: 'a', title: 'A' }),
    makeTrack({ id: 'b', title: 'B' }),
    makeTrack({ id: 'c', title: 'C' }),
    makeTrack({ id: 'd', title: 'D' })
  ];
}

beforeEach(() => clearSelection());

describe('selection store', () => {
  test('starts empty + inactive', () => {
    expect(selection.count).toBe(0);
    expect(selection.active).toBe(false);
    expect(selection.tracks).toEqual([]);
  });

  test('toggleOne selects and deselects', () => {
    const ts = tracks();
    toggleOne(ts[1], 1);
    expect(selection.isSelected('b')).toBe(true);
    expect(selection.count).toBe(1);
    expect(selection.active).toBe(true);

    toggleOne(ts[1], 1);
    expect(selection.isSelected('b')).toBe(false);
    expect(selection.count).toBe(0);
    expect(selection.active).toBe(false);
  });

  test('selectRange extends from the last anchor inclusive', () => {
    const ts = tracks();
    toggleOne(ts[0], 0);
    selectRange(2, ts);
    expect(selection.isSelected('a')).toBe(true);
    expect(selection.isSelected('b')).toBe(true);
    expect(selection.isSelected('c')).toBe(true);
    expect(selection.isSelected('d')).toBe(false);
    expect(selection.count).toBe(3);
  });

  test('selectRange handles reverse direction', () => {
    const ts = tracks();
    toggleOne(ts[3], 3);
    selectRange(1, ts);
    expect(selection.isSelected('b')).toBe(true);
    expect(selection.isSelected('c')).toBe(true);
    expect(selection.isSelected('d')).toBe(true);
    expect(selection.isSelected('a')).toBe(false);
  });

  test('selectRange with no anchor collapses to a single toggle', () => {
    const ts = tracks();
    selectRange(2, ts);
    expect(selection.isSelected('c')).toBe(true);
    expect(selection.count).toBe(1);
  });

  test('selection.tracks returns the full TrackRef payloads', () => {
    const ts = tracks();
    toggleOne(ts[0], 0);
    toggleOne(ts[2], 2);
    const picked = selection.tracks;
    const titles = picked.map((t) => t.title).sort();
    expect(titles).toEqual(['A', 'C']);
  });

  test('clearSelection resets state', () => {
    const ts = tracks();
    toggleOne(ts[0], 0);
    toggleOne(ts[1], 1);
    clearSelection();
    expect(selection.count).toBe(0);
    expect(selection.active).toBe(false);

    // Anchor is reset too — a follow-up range collapses to one.
    selectRange(2, ts);
    expect(selection.count).toBe(1);
  });
});
