import React from 'react';
import { render, screen, fireEvent } from '@testing-library/react';
import { Expandable, ExpandableProps } from '../index';

describe('<Expandable>', () => {
    const defaultProps: ExpandableProps = {
        children: (
            <>
                <Expandable.Trigger testId="ExpandableTrigger">Toggle</Expandable.Trigger>
                <Expandable.Body testId="ExpandableBody">Content</Expandable.Body>
            </>
        ),
    };

    const renderComponent = (props: Partial<ExpandableProps> = {}) =>
        render(<Expandable {...defaultProps} {...props} />);

    describe('uncontrolled mode', () => {
        test('starts expanded by default', () => {
            renderComponent();
            const body = screen.getByTestId('ExpandableBody');
            expect(body).not.toHaveClass('ExpandableBody-collapsed');
            expect(body).toHaveAttribute('aria-hidden', 'false');
        });

        test('starts expanded when defaultExpanded is true', () => {
            renderComponent({ defaultExpanded: true });
            const body = screen.getByTestId('ExpandableBody');
            expect(body).not.toHaveClass('ExpandableBody-collapsed');
            expect(body).toHaveAttribute('aria-hidden', 'false');
        });

        test('toggles expansion when trigger is clicked', () => {
            renderComponent();
            const trigger = screen.getByTestId('ExpandableTrigger');
            const body = screen.getByTestId('ExpandableBody');

            // Initially expanded
            expect(body).not.toHaveClass('ExpandableBody-collapsed');

            // Click to collapse
            fireEvent.click(trigger);
            expect(body).toHaveClass('ExpandableBody-collapsed');
            expect(body).toHaveAttribute('aria-hidden', 'true');

            // Click to expand
            fireEvent.click(trigger);
            expect(body).not.toHaveClass('ExpandableBody-collapsed');
            expect(body).toHaveAttribute('aria-hidden', 'false');
        });
    });

    describe('controlled mode', () => {
        test('uses controlled expanded prop', () => {
            const { rerender } = renderComponent({ expanded: false });
            const body = screen.getByTestId('ExpandableBody');

            expect(body).toHaveClass('ExpandableBody-collapsed');

            rerender(
                <Expandable {...defaultProps} expanded={true}>
                    {defaultProps.children}
                </Expandable>
            );
            expect(body).not.toHaveClass('ExpandableBody-collapsed');
        });

        test('calls onExpanded when trigger is clicked', () => {
            const onExpanded = vi.fn();
            renderComponent({ expanded: false, onExpanded });

            const trigger = screen.getByTestId('ExpandableTrigger');
            fireEvent.click(trigger);

            expect(onExpanded).toHaveBeenCalledWith(true);
        });

        test('does not change state internally in controlled mode', () => {
            const onExpanded = vi.fn();
            renderComponent({ expanded: false, onExpanded });

            const trigger = screen.getByTestId('ExpandableTrigger');
            const body = screen.getByTestId('ExpandableBody');
            expect(body).toHaveClass('ExpandableBody-collapsed');

            fireEvent.click(trigger);

            // State should not change without parent updating the prop
            expect(body).toHaveClass('ExpandableBody-collapsed');
            expect(onExpanded).toHaveBeenCalledWith(true);
        });
    });

    describe('isExpandable bypass mode', () => {
        test('renders children without expandable classes, trigger or body', () => {
            const r = renderComponent({
                isExpandable: false,
                children: <div data-testid="nonExpDiv">NonExpandableContent</div>,
            });

            const el = r.getByTestId('nonExpDiv');
            expect(el).toHaveTextContent('NonExpandableContent');

            expect(r.container.getElementsByClassName('ExpandableTrigger').length).toBe(0);
            expect(r.container.getElementsByClassName('ExpandableBody').length).toBe(0);
        });
    });
});
