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

afterEach(cleanup);

const baseProps = (overrides: Record<string, unknown> = {}) => ({
	senderId: '',
	receiverId: '',
	fromDate: '',
	toDate: '',
	sortDir: 'DESC',
	initialSenderName: '',
	initialReceiverName: '',
	onapplyFilters: () => {},
	ontoggleSort: () => {},
	onswapPersons: () => {},
	...overrides
});

describe('ConversationFilterBar', () => {
	it('renders the two PersonTypeahead inputs and the date inputs', async () => {
		render(ConversationFilterBar, { props: baseProps() });

		const dateInputs = document.querySelectorAll('input[type="date"]');
		expect(dateInputs.length).toBe(2);
	});

	it('marks the swap button invisible when only one person is set', async () => {
		render(ConversationFilterBar, { props: baseProps({ senderId: 'p1' }) });

		const swap = document.querySelector('[data-testid="conv-swap-btn"]') as HTMLElement;
		expect(swap.className).toContain('invisible');
	});

	it('marks the swap button visible when both persons are set', async () => {
		render(ConversationFilterBar, {
			props: baseProps({ senderId: 'p1', receiverId: 'p2' })
		});

		const swap = document.querySelector('[data-testid="conv-swap-btn"]') as HTMLElement;
		expect(swap.className).not.toContain('invisible');
	});

	it('renders "Neueste zuerst" when sortDir is DESC', async () => {
		render(ConversationFilterBar, { props: baseProps({ sortDir: 'DESC' }) });

		await expect.element(page.getByText('Neueste zuerst')).toBeVisible();
	});

	it('renders "Älteste zuerst" when sortDir is ASC', async () => {
		render(ConversationFilterBar, { props: baseProps({ sortDir: 'ASC' }) });

		await expect.element(page.getByText('Älteste zuerst')).toBeVisible();
	});

	it('rotates the chevron 180° when sortDir is ASC', async () => {
		render(ConversationFilterBar, { props: baseProps({ sortDir: 'ASC' }) });

		const sortBtn = Array.from(document.querySelectorAll('button')).find((b) =>
			b.textContent?.toLowerCase().includes('älteste')
		);
		const chevron = sortBtn?.querySelector('svg');
		expect(chevron?.getAttribute('class')).toContain('rotate-180');
	});

	it('does not rotate the chevron when sortDir is DESC', async () => {
		render(ConversationFilterBar, { props: baseProps({ sortDir: 'DESC' }) });

		const sortBtn = Array.from(document.querySelectorAll('button')).find((b) =>
			b.textContent?.toLowerCase().includes('neueste')
		);
		const chevron = sortBtn?.querySelector('svg');
		expect(chevron?.getAttribute('class')).not.toContain('rotate-180');
	});

	it('calls ontoggleSort when the sort button is clicked', async () => {
		const ontoggleSort = vi.fn();
		render(ConversationFilterBar, { props: baseProps({ ontoggleSort }) });

		const sortBtn = Array.from(document.querySelectorAll('button')).find((b) =>
			b.textContent?.toLowerCase().includes('neueste')
		);
		sortBtn?.click();
		expect(ontoggleSort).toHaveBeenCalledOnce();
	});

	it('calls onswapPersons when the swap button is clicked', async () => {
		const onswapPersons = vi.fn();
		render(ConversationFilterBar, {
			props: baseProps({ senderId: 'p1', receiverId: 'p2', onswapPersons })
		});

		const swap = document.querySelector('[data-testid="conv-swap-btn"]') as HTMLElement;
		swap.click();
		expect(onswapPersons).toHaveBeenCalledOnce();
	});

	it('calls onapplyFilters when fromDate input changes', async () => {
		const onapplyFilters = vi.fn();
		render(ConversationFilterBar, { props: baseProps({ onapplyFilters }) });

		const fromInput = document.querySelector('#dateFrom') as HTMLInputElement;
		fromInput.value = '1899-04-14';
		fromInput.dispatchEvent(new Event('change', { bubbles: true }));
		expect(onapplyFilters).toHaveBeenCalled();
	});

	it('calls onapplyFilters when toDate input changes', async () => {
		const onapplyFilters = vi.fn();
		render(ConversationFilterBar, { props: baseProps({ onapplyFilters }) });

		const toInput = document.querySelector('#dateTo') as HTMLInputElement;
		toInput.value = '1950-12-31';
		toInput.dispatchEvent(new Event('change', { bubbles: true }));
		expect(onapplyFilters).toHaveBeenCalled();
	});
});
