import { describe, it, expect, afterEach } from 'vitest';
import { cleanup, render } from 'vitest-browser-svelte';
import { page } from 'vitest/browser';

import ChronikTimeline from './ChronikTimeline.svelte';
import type { components } from '$lib/generated/api';

type ActivityFeedItemDTO = components['schemas']['ActivityFeedItemDTO'];

afterEach(cleanup);

function item(partial: Partial<ActivityFeedItemDTO>): ActivityFeedItemDTO {
	return {
		kind: 'TEXT_SAVED',
		actor: { initials: 'AB', color: '#123456', name: 'Anna Beta' },
		documentId: 'doc-x',
		documentTitle: 'Some document',
		happenedAt: new Date().toISOString(),
		youMentioned: false,
		count: 1,
		...partial
	};
}

function atOffsetDays(days: number): string {
	const d = new Date();
	d.setDate(d.getDate() - days);
	return d.toISOString();
}

describe('ChronikTimeline', () => {
	it('renders nothing / no bucket headers when items is empty', async () => {
		render(ChronikTimeline, { items: [] });
		expect(document.querySelector('[data-testid="chronik-bucket-today"]')).toBeNull();
		expect(document.querySelector('[data-testid="chronik-bucket-yesterday"]')).toBeNull();
		expect(document.querySelector('[data-testid="chronik-bucket-thisWeek"]')).toBeNull();
		expect(document.querySelector('[data-testid="chronik-bucket-older"]')).toBeNull();
	});

	it('places today items in the today bucket with a "Heute" header', async () => {
		render(ChronikTimeline, {
			items: [
				item({
					documentId: 'doc-today',
					documentTitle: 'Frisches Dokument',
					happenedAt: new Date().toISOString()
				})
			]
		});
		const today = document.querySelector('[data-testid="chronik-bucket-today"]');
		expect(today).not.toBeNull();
		await expect.element(page.getByText('Heute', { exact: true })).toBeInTheDocument();
		// The row for the today item should be inside the today bucket.
		expect(today?.textContent).toContain('Frisches Dokument');
	});

	it('does not render an empty bucket header when no items fall into it', async () => {
		render(ChronikTimeline, {
			items: [item({ happenedAt: new Date().toISOString() })]
		});
		// Only today bucket should exist.
		expect(document.querySelector('[data-testid="chronik-bucket-today"]')).not.toBeNull();
		expect(document.querySelector('[data-testid="chronik-bucket-older"]')).toBeNull();
	});

	it('places older items in the older bucket', async () => {
		render(ChronikTimeline, {
			items: [
				item({
					documentId: 'doc-old',
					documentTitle: 'Alt Doc',
					happenedAt: atOffsetDays(30)
				})
			]
		});
		const older = document.querySelector('[data-testid="chronik-bucket-older"]');
		expect(older).not.toBeNull();
		expect(older?.textContent).toContain('Alt Doc');
	});

	it('groups multiple items into their respective buckets', async () => {
		render(ChronikTimeline, {
			items: [
				item({
					documentId: 'd1',
					documentTitle: 'Heute Item',
					happenedAt: new Date().toISOString()
				}),
				item({ documentId: 'd2', documentTitle: 'Alt Item', happenedAt: atOffsetDays(30) })
			]
		});
		const today = document.querySelector('[data-testid="chronik-bucket-today"]');
		const older = document.querySelector('[data-testid="chronik-bucket-older"]');
		expect(today?.textContent).toContain('Heute Item');
		expect(today?.textContent).not.toContain('Alt Item');
		expect(older?.textContent).toContain('Alt Item');
		expect(older?.textContent).not.toContain('Heute Item');
	});
});
