import { describe, it, expect, vi, afterEach } from 'vitest';
import { render, fireEvent, screen, cleanup } from '@testing-library/svelte';
import Combobox from './Combobox.svelte';
const mockOptions = [
    { value: 'apple', label: 'Apple' },
    { value: 'banana', label: 'Banana' },
    { value: 'cherry', label: 'Cherry' },
    { value: 'date', label: 'Date' },
];
const getControl = () => screen.getByRole('combobox', { name: /combobox input/i });
const getControlAsButton = () => screen.getByRole('button', { name: /combobox input/i });
describe('Combobox', () => {
    afterEach(() => {
        cleanup();
        vi.restoreAllMocks();
    });
    describe('Rendering', () => {
        it('renders the combobox control element', () => {
            render(Combobox, { props: { value: null, options: mockOptions } });
            expect(getControl()).toBeTruthy();
        });
        it('shows placeholder when no value', () => {
            render(Combobox, {
                props: { value: null, options: mockOptions, placeholder: 'Pick something' },
            });
            expect(screen.getByText('Pick something')).toBeTruthy();
        });
        it('shows counterlabel in multiple mode (non-compact)', () => {
            render(Combobox, {
                props: {
                    value: ['apple', 'banana'],
                    options: mockOptions,
                    multiple: true,
                    counterlabel: '2 selected',
                },
            });
            expect(screen.getByText('2 selected')).toBeTruthy();
        });
        it('shows joined values as label in multiple+compact mode', () => {
            render(Combobox, {
                props: {
                    value: ['apple', 'banana'],
                    options: mockOptions,
                    multiple: true,
                    compact: true,
                },
            });
            expect(screen.getByText('Apple, Banana')).toBeTruthy();
        });
        it('does not render removable tags in compact mode', () => {
            render(Combobox, {
                props: { value: ['apple'], options: mockOptions, multiple: true, compact: true },
            });
            expect(screen.queryByLabelText(/remove/i)).toBeNull();
        });
        it('renders as a native button (no role override) when search prop is true', () => {
            render(Combobox, { props: { value: null, options: mockOptions, search: true } });
            expect(getControlAsButton()).toBeTruthy();
        });
    });
    describe('CSS modifier classes', () => {
        it('applies mc-combobox--multiple when multiple', () => {
            const { container } = render(Combobox, {
                props: { value: [], options: mockOptions, multiple: true },
            });
            expect(container.querySelector('.mc-combobox--multiple')).toBeTruthy();
        });
        it('applies mc-combobox--invalid when invalid', () => {
            const { container } = render(Combobox, {
                props: { value: null, options: mockOptions, invalid: true },
            });
            expect(container.querySelector('.mc-combobox--invalid')).toBeTruthy();
        });
        it('applies mc-combobox--disabled when disabled', () => {
            const { container } = render(Combobox, {
                props: { value: null, options: mockOptions, disabled: true },
            });
            expect(container.querySelector('.mc-combobox--disabled')).toBeTruthy();
        });
        it('applies mc-combobox--readonly when readonly', () => {
            const { container } = render(Combobox, {
                props: { value: null, options: mockOptions, readonly: true },
            });
            expect(container.querySelector('.mc-combobox--readonly')).toBeTruthy();
        });
        it('applies mc-combobox--s for size s', () => {
            const { container } = render(Combobox, {
                props: { value: null, options: mockOptions, size: 's' },
            });
            expect(container.querySelector('.mc-combobox--s')).toBeTruthy();
        });
        it('does NOT apply mc-combobox--s for size m', () => {
            const { container } = render(Combobox, {
                props: { value: null, options: mockOptions, size: 'm' },
            });
            expect(container.querySelector('.mc-combobox--s')).toBeNull();
        });
    });
    describe('Open / Close behaviour', () => {
        it('opens the listbox when the control is clicked', async () => {
            const { container } = render(Combobox, { props: { value: null, options: mockOptions } });
            await fireEvent.click(getControl());
            expect(container.querySelector('.mc-combobox--open')).toBeTruthy();
        });
        it('closes the listbox on second click (toggle)', async () => {
            const { container } = render(Combobox, { props: { value: null, options: mockOptions } });
            const control = getControl();
            await fireEvent.click(control);
            await fireEvent.click(control);
            expect(container.querySelector('.mc-combobox--open')).toBeNull();
        });
        it('opens the listbox when the chevron icon button is clicked', async () => {
            const { container } = render(Combobox, { props: { value: null, options: mockOptions } });
            await fireEvent.click(screen.getByRole('button', { name: /expand options list/i }));
            expect(container.querySelector('.mc-combobox--open')).toBeTruthy();
        });
        it('closes the listbox on outside click', async () => {
            const { container } = render(Combobox, { props: { value: null, options: mockOptions } });
            await fireEvent.click(getControl());
            expect(container.querySelector('.mc-combobox--open')).toBeTruthy();
            await fireEvent.click(document.body);
            expect(container.querySelector('.mc-combobox--open')).toBeNull();
        });
        it('sets aria-expanded=true when open', async () => {
            render(Combobox, { props: { value: null, options: mockOptions } });
            const control = getControl();
            await fireEvent.click(control);
            expect(control.getAttribute('aria-expanded')).toBe('true');
        });
        it('sets aria-expanded=false when closed', () => {
            render(Combobox, { props: { value: null, options: mockOptions } });
            expect(getControl().getAttribute('aria-expanded')).toBe('false');
        });
    });
    describe('Clear button', () => {
        it('shows clear button when clearable and a single value is selected', () => {
            render(Combobox, {
                props: { value: 'apple', options: mockOptions, clearable: true },
            });
            expect(screen.getByRole('button', { name: /clear value/i })).toBeTruthy();
        });
        it('does not show clear button when no value is selected', () => {
            render(Combobox, {
                props: { value: null, options: mockOptions, clearable: true },
            });
            expect(screen.queryByRole('button', { name: /clear value/i })).toBeNull();
        });
        it('does not show clear button when clearable is false', () => {
            render(Combobox, {
                props: { value: 'apple', options: mockOptions, clearable: false },
            });
            expect(screen.queryByRole('button', { name: /clear value/i })).toBeNull();
        });
        it('resets single value to null when clear button is clicked', async () => {
            render(Combobox, {
                props: { value: 'apple', options: mockOptions, clearable: true },
            });
            await fireEvent.click(screen.getByRole('button', { name: /clear value/i }));
            expect(screen.getByText('Select an option')).toBeTruthy();
        });
        it('resets multiple value to [] when clear button is clicked', async () => {
            render(Combobox, {
                props: {
                    value: ['apple', 'banana'],
                    options: mockOptions,
                    clearable: true,
                    multiple: true,
                },
            });
            await fireEvent.click(screen.getByRole('button', { name: /clear value/i }));
            expect(screen.getByText('Select an option')).toBeTruthy();
        });
        it('shows clear button in multiple mode when at least one item is selected', () => {
            render(Combobox, {
                props: { value: ['apple'], options: mockOptions, clearable: true, multiple: true },
            });
            expect(screen.getByRole('button', { name: /clear value/i })).toBeTruthy();
        });
        it('hides clear button in multiple mode when value is empty', () => {
            render(Combobox, {
                props: { value: [], options: mockOptions, clearable: true, multiple: true },
            });
            expect(screen.queryByRole('button', { name: /clear value/i })).toBeNull();
        });
    });
});
