import { describe, it, expect, vi, beforeEach } from 'vitest';

// Mock $app/environment
vi.mock('$app/environment', () => ({
	browser: true
}));

import { isOffline, recordSync, getLastSyncDate, prefetchScheduleDays } from '$lib/features/schedule/stores/scheduleCache.svelte';

describe('scheduleCache', () => {
	beforeEach(() => {
		localStorage.clear();
	});

	describe('isOffline', () => {
		it('returns false when navigator is online', () => {
			Object.defineProperty(navigator, 'onLine', { value: true, configurable: true });
			expect(isOffline()).toBe(false);
		});

		it('returns true when navigator is offline', () => {
			Object.defineProperty(navigator, 'onLine', { value: false, configurable: true });
			expect(isOffline()).toBe(true);
		});
	});

	describe('sync tracking', () => {
		it('returns null when no sync has been recorded', () => {
			expect(getLastSyncDate()).toBeNull();
		});

		it('records and retrieves the last sync date', () => {
			recordSync();
			const date = getLastSyncDate();
			expect(date).not.toBeNull();
			expect(new Date(date!).getTime()).toBeGreaterThan(0);
		});
	});

	describe('prefetchScheduleDays', () => {
		it('prefetches 7 past days + today + 23 future days (31 total)', async () => {
			const fetchFn = vi.fn().mockResolvedValue({});
			const today = new Date('2026-03-10');

			await prefetchScheduleDays(fetchFn, today);

			// 7 past + 1 today + 23 future = 31 calls
			expect(fetchFn).toHaveBeenCalledTimes(31);
			// First call: 7 days ago
			expect(fetchFn).toHaveBeenCalledWith('2026-03-03');
			// Today
			expect(fetchFn).toHaveBeenCalledWith('2026-03-10');
			// Last call: 23 days ahead
			expect(fetchFn).toHaveBeenCalledWith('2026-04-02');
		});

		it('silently handles fetch failures', async () => {
			const fetchFn = vi.fn()
				.mockResolvedValueOnce({})
				.mockRejectedValueOnce(new Error('Network error'))
				.mockResolvedValue({});

			await expect(
				prefetchScheduleDays(fetchFn, new Date('2026-03-02'))
			).resolves.toBeUndefined();

			expect(fetchFn).toHaveBeenCalledTimes(31);
		});
	});
});
