import { describe, it, expect, vi, afterEach } from 'vitest';
import { render, screen, cleanup, fireEvent } from '@testing-library/svelte';
import { createRawSnippet } from 'svelte';
import IconButton from './IconButton.svelte';

afterEach(() => cleanup());

// A stand-in for the lucide icon callers pass as the child.
const icon = createRawSnippet(() => ({
    render: () => `<svg data-testid="glyph"></svg>`
}));

describe('IconButton', () => {
    it('renders a button containing the icon child', () => {
        render(IconButton, { props: { children: icon } });
        const btn = screen.getByRole('button');
        expect(btn.querySelector('[data-testid="glyph"]')).toBeTruthy();
    });

    it('defaults to type=button so it never submits a surrounding form by accident', () => {
        render(IconButton, { props: { children: icon } });
        expect(screen.getByRole('button').getAttribute('type')).toBe('button');
    });

    it('lets a caller override the type (e.g. submit)', () => {
        render(IconButton, { props: { type: 'submit', children: icon } });
        expect(screen.getByRole('button').getAttribute('type')).toBe('submit');
    });

    it('applies the variant as a class (plain by default)', () => {
        const { container } = render(IconButton, { props: { children: icon } });
        expect(container.querySelector('button.icon-btn.plain')).toBeTruthy();
        cleanup();
        const { container: c2 } = render(IconButton, {
            props: { variant: 'danger', children: icon }
        });
        expect(c2.querySelector('button.icon-btn.danger')).toBeTruthy();
    });

    it('defaults to a 32px square with the small radius', () => {
        const { container } = render(IconButton, { props: { children: icon } });
        const btn = container.querySelector('button.icon-btn') as HTMLButtonElement;
        expect(btn.classList.contains('radius-sm')).toBe(true);
        expect(btn.style.getPropertyValue('--ib-size')).toBe('32px');
    });

    it('honours an explicit size and radius (the larger header/search buttons)', () => {
        const { container } = render(IconButton, {
            props: { size: 36, radius: 'md', children: icon }
        });
        const btn = container.querySelector('button.icon-btn') as HTMLButtonElement;
        expect(btn.style.getPropertyValue('--ib-size')).toBe('36px');
        expect(btn.classList.contains('radius-md')).toBe(true);
        expect(btn.classList.contains('radius-sm')).toBe(false);
    });

    it('forwards onclick', async () => {
        const onclick = vi.fn();
        render(IconButton, { props: { onclick, children: icon } });
        await fireEvent.click(screen.getByRole('button'));
        expect(onclick).toHaveBeenCalledOnce();
    });

    it('forwards arbitrary button attributes (aria-label, title, disabled, data-testid)', () => {
        render(IconButton, {
            props: {
                'aria-label': 'Delete collection',
                title: 'Delete',
                disabled: true,
                'data-testid': 'collection-delete',
                children: icon
            }
        });
        const btn = screen.getByTestId('collection-delete');
        expect(btn.getAttribute('aria-label')).toBe('Delete collection');
        expect(btn.getAttribute('title')).toBe('Delete');
        expect((btn as HTMLButtonElement).disabled).toBe(true);
    });
});
