import React from 'react';
import { render, fireEvent, waitFor } from '@testing-library/react';
import * as suiteConfig from '@theorchard/suite-config';
import { MemoryRouter } from 'react-router-dom';
import { MainNavFooterUserMenu, MainNavFooterUserMenuProps } from '../mainNavFooterUserMenu';

vi.mock('@theorchard/suite-config');

const mockImageLoad = () => {
    global.Image = class {
        onload: () => void;

        constructor() {
            this.onload = vi.fn();

            setTimeout(() => {
                this.onload();
            }, 1);
        }
    } as never;
};

describe('<MainNavFooterUserMenu>', () => {
    const renderComponent = (props: MainNavFooterUserMenuProps, pathname = '/') =>
        render(<MainNavFooterUserMenu {...props} />, {
            wrapper: ({ children }) => (
                <MemoryRouter initialEntries={[{ pathname }]}>{children}</MemoryRouter>
            ),
        });

    beforeAll(() => {
        mockImageLoad();
    });

    beforeEach(() => {
        vi.spyOn(suiteConfig, 'useAppConfig').mockReturnValue({
            brand: 'orchard',
        } as unknown as suiteConfig.SuiteAppConfig);
    });

    test('renders user name', () => {
        const name = 'test user';
        const { getByText } = renderComponent({ name });
        expect(getByText(name)).toBeVisible();
    });

    test('renders user picture', async () => {
        const picture = 'test.image.jpg';

        const { container } = renderComponent({ picture });

        await waitFor(() => {
            const image = container.querySelector('.UserThumb-image');
            expect(image?.getAttribute('src')).toEqual(picture);
        });
    });

    test('invokes "onClick" callback', () => {
        const onClick = vi.fn();
        const menuItem = 'test item';
        const testId = 'outerBtn';

        const { getByTestId, getByText, container } = renderComponent({
            onClick,
            testId,
            items: [{ path: '/test', title: menuItem }],
        });
        const btn = getByTestId(testId);
        const item = getByText(menuItem);
        const toggle = container.querySelector('.MainNavFooterUserMenu-toggle');

        fireEvent.click(btn);
        expect(onClick).toHaveBeenCalledTimes(1);

        fireEvent.click(item);
        expect(onClick).toHaveBeenCalledTimes(2);

        if (!toggle) throw new Error('Could not find toggle btn');
        fireEvent.click(toggle);
        expect(onClick).toHaveBeenCalledTimes(3);
    });

    describe('without picture', () => {
        test('renders user initials', () => {
            const name = 'Captain america';
            const { getByText } = renderComponent({ name });
            const image = getByText('CA');
            expect(image).toBeVisible();
        });
    });

    describe('with menu items', () => {
        test('renders items', () => {
            const title1 = 'menu item 1';
            const title2 = 'menu item 2';

            const { getByText } = renderComponent({
                items: [
                    { path: 'test1', title: title1 },
                    { path: 'test2', title: title2 },
                ],
            });
            expect(getByText(title1)).toBeVisible();
            expect(getByText(title2)).toBeVisible();
        });

        test('renders custom items', () => {
            const title1 = 'menu item 1';
            const title2 = 'custom menu item 2';

            const { getByText } = renderComponent({
                items: [
                    { path: 'test1', title: title1 },
                    { path: 'test2', Component: () => <div>{title2}</div> },
                ],
            });
            expect(getByText(title1)).toBeVisible();
            expect(getByText(title2)).toBeVisible();
        });
    });
});
