/**
 * Unit tests for selectSnippetsWithinBudget (TRUEREF-0010).
 */

import { describe, it, expect } from 'vitest';
import { selectSnippetsWithinBudget, DEFAULT_TOKEN_BUDGET } from './token-budget';
import type { Snippet } from '$lib/types';

// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------

function makeSnippet(id: string, tokenCount: number | null): Snippet {
	return {
		id,
		documentId: 'doc-1',
		repositoryId: '/test/repo',
		versionId: null,
		type: 'info',
		title: null,
		content: 'content',
		language: null,
		breadcrumb: null,
		tokenCount,
		createdAt: new Date()
	};
}

// ---------------------------------------------------------------------------
// Tests
// ---------------------------------------------------------------------------

describe('selectSnippetsWithinBudget', () => {
	it('returns all snippets when total tokens are within budget', () => {
		const snippets = [makeSnippet('a', 100), makeSnippet('b', 200), makeSnippet('c', 300)];
		const result = selectSnippetsWithinBudget(snippets, 1000);
		expect(result.map((s) => s.id)).toEqual(['a', 'b', 'c']);
	});

	it('stops adding when next snippet exceeds the budget', () => {
		const snippets = [makeSnippet('a', 100), makeSnippet('b', 500), makeSnippet('c', 200)];
		// budget = 550 → a (100) + b (500) = 600 exceeds; only a fits then b would push over
		const result = selectSnippetsWithinBudget(snippets, 550);
		// a(100) fits; a+b=600 > 550, stop
		expect(result.map((s) => s.id)).toEqual(['a']);
	});

	it('includes exactly one snippet when it fits the budget precisely', () => {
		const snippets = [makeSnippet('a', 100)];
		const result = selectSnippetsWithinBudget(snippets, 100);
		expect(result.map((s) => s.id)).toEqual(['a']);
	});

	it('returns empty array when first snippet already exceeds budget', () => {
		const snippets = [makeSnippet('a', 200), makeSnippet('b', 50)];
		const result = selectSnippetsWithinBudget(snippets, 100);
		expect(result).toHaveLength(0);
	});

	it('treats null tokenCount as 0', () => {
		const snippets = [makeSnippet('a', null), makeSnippet('b', null), makeSnippet('c', null)];
		const result = selectSnippetsWithinBudget(snippets, 0);
		// 0 + 0 = 0 which does NOT exceed 0, so all three pass
		expect(result.map((s) => s.id)).toEqual(['a', 'b', 'c']);
	});

	it('returns empty array for empty input', () => {
		const result = selectSnippetsWithinBudget([], 10_000);
		expect(result).toHaveLength(0);
	});

	it('DEFAULT_TOKEN_BUDGET is 10000', () => {
		expect(DEFAULT_TOKEN_BUDGET).toBe(10_000);
	});
});
