import React from 'react';
import { render as renderDom, screen, fireEvent } from '@testing-library/react';
import { CLASSNAME } from '../constants';
import { Sidebar, Props } from '../sidebar';

describe('Sidebar', () => {
    const defaultProps: Props = {
        isOpen: true,
        onRequestClose: vitest.fn(),
        children: <span>TEST</span>,
    };

    beforeEach(() => {
        const portal = document.createElement('div');
        portal.classList.add('SuiteSidebarPortal');
        document.body.appendChild(portal);
    });

    afterEach(() => {
        const portal = document.querySelector('.SuiteSidebarPortal');
        if (portal) document.body.removeChild(portal);
    });

    const render = (props?: Partial<Props>) =>
        renderDom(
            <>
                <Sidebar {...defaultProps} {...props} />
            </>
        );

    test('renders correctly', () => {
        render();

        const text = screen.getByText('TEST');
        expect(text).toBeInTheDocument();
        expect(text.closest('.SuiteSidebar')).toBeInTheDocument();
        expect(document.getElementsByClassName('SuiteSidebar-header').item(0)).toBeInTheDocument();
    });

    test('accepts classname and testId', () => {
        const className = 'FAKE-CLASS';
        const testId = 'FAKE-id';
        render({ className, testId });

        expect(screen.getByTestId(testId)).toBeInTheDocument();
        expect(screen.getByTestId(testId)).toHaveClass(CLASSNAME);
        expect(screen.getByTestId(testId)).toHaveClass(className);
    });

    describe('portal', () => {
        test('defaults to SuiteSidebarPortal element', () => {
            render();

            const sidebar = screen.getByText('TEST');
            expect(sidebar).toBeInTheDocument();
            expect(sidebar.closest('.SuiteSidebarPortal')).toBeInTheDocument();
        });

        test('supports custom portal', () => {
            const portal = document.createElement('div');
            portal.id = 'portal-test';
            document.body.appendChild(portal);

            render({ portalElement: portal });
            const sidebar = screen.getByText('TEST');
            expect(portal).toContain(sidebar);

            document.body.removeChild(portal);
        });
    });

    describe('isOpen prop', () => {
        test('renders when isOpen=true', () => {
            render({ isOpen: true });
            expect(screen.getByTestId('SuiteSidebar')).toBeInTheDocument();
            expect(screen.getByText('TEST')).toBeInTheDocument();
            expect(screen.getByTestId('SuiteSidebar')).toHaveClass('open');
        });

        test('renders content when isOpen=false and unmountOnClose=false', () => {
            render({ isOpen: false, unmountOnClose: false });

            const sidebar = screen.getByTestId('SuiteSidebar');
            expect(sidebar).toBeInTheDocument();
            expect(sidebar).not.toHaveClass('open');
            expect(screen.getByText('TEST')).toBeInTheDocument();
        });

        test('does not render content when isOpen=false and transitionend has fired', () => {
            const component = render({ isOpen: true });
            expect(screen.getByText('TEST')).toBeInTheDocument();

            component.rerender(<Sidebar {...defaultProps} isOpen={false} />);
            expect(screen.getByText('TEST')).toBeInTheDocument();

            const container = screen.getByText('TEST').parentNode;
            if (container) fireEvent.transitionEnd(container);
            expect(screen.queryByText('TEST')).toBeNull();
        });
    });
});
