import React from 'react';
import { render } from '@testing-library/react';
import * as AppConfigModule from '@theorchard/suite-frontend';
import { createIdentity, createRole } from 'lib/test-utils/identity-factory';
import { MemoryRouter } from 'react-router-dom';
import { mockAppConfig } from '../../../../lib/test-helpers/factories';
import IdentityContext from '../../../context';
import SitemapItems from '../sitemap-items';

jest.mock('@theorchard/suite-frontend', () => ({
    __esModule: true,
    ...jest.requireActual('@theorchard/suite-frontend'),
}));

// Mock LegacyLink and ReactifiedLink to capture which is rendered
jest.mock('../legacy-link', () => ({
    __esModule: true,
    default: ({ term }: { term: string }) => (
        <a data-testid="legacy-link" data-term={term} href="#">
            {term}
        </a>
    ),
}));

jest.mock('../reactified-link', () => ({
    __esModule: true,
    default: ({ term }: { term: string }) => (
        <a data-testid="reactified-link" data-term={term} href="#">
            {term}
        </a>
    ),
    CLASSNAME: 'nav-link',
}));

describe('<SitemapItems>', () => {
    const className = 'sitemap';
    const defaultProps = {
        className,
    };

    const defaultConfig = {
        roles: [
            createRole('analytics'),
            createRole('catalog', 'index'),
            createRole('accounting'),
            createRole('marketing'),
        ],
        featureFlags: {
            analytics_comparison: 'enabled',
        },
        restrictedFeatures: ['feature'],
    };

    const renderComponent = (
        props: Record<string, unknown> = {},
        config: Record<string, unknown> = {},
        hasFeatureFlag = false
    ) => {
        const identity = createIdentity({
            ...defaultConfig,
            ...config,
        } as any);
        if (hasFeatureFlag)
            jest.spyOn(identity, 'hasFeatureFlag').mockReturnValue(true);

        return render(
            <MemoryRouter>
                <IdentityContext.Provider value={{ identity } as any}>
                    <SitemapItems
                        {...defaultProps}
                        {...(props as Record<string, unknown>)}
                    />
                </IdentityContext.Provider>
            </MemoryRouter>
        );
    };

    beforeEach(() => {
        jest.spyOn(AppConfigModule, 'useAppConfig').mockReturnValue(
            mockAppConfig
        );
    });

    afterEach(() => {
        jest.restoreAllMocks();
    });

    describe('routes with no module', () => {
        const item1 = { key: 'Item1', url: 'link1' };
        const items = [item1];

        test('renders legacy links', () => {
            const { getAllByTestId } = renderComponent({ items });
            const links = getAllByTestId('legacy-link');
            expect(links).toHaveLength(items.length);
        });
    });

    describe('routes with module', () => {
        const item1 = { key: 'Item1', url: 'link1', module: 'test' };
        const items = [item1];

        test('renders reactified links', () => {
            const { getAllByTestId } = renderComponent({ items });
            const links = getAllByTestId('reactified-link');
            expect(links).toHaveLength(items.length);
        });
    });

    describe('is running on top of a php environment', () => {
        const item1 = { key: 'Item1', url: 'link1', module: 'test' };
        const item2 = { key: 'Item2', url: 'link2' };
        const items = [item1, item2];

        test('renders only legacy links', () => {
            const { getAllByTestId, queryAllByTestId } = renderComponent({
                items,
                isEmbedOnPhp: true,
            });
            expect(getAllByTestId('legacy-link')).toHaveLength(items.length);
            expect(queryAllByTestId('reactified-link')).toHaveLength(0);
        });
    });

    test('filters non-accessible routes', () => {
        const items = [
            { key: 'Item1', url: 'link1', featureFlag: 'hidden' },
            { key: 'Item2', url: 'link1', permission: 'hidden' },
            { key: 'Item3', url: 'link1', featureControl: 'feature' },
            { key: 'Item4' },
        ];

        const { queryAllByTestId } = renderComponent({ items });
        expect(queryAllByTestId('legacy-link')).toHaveLength(0);
        expect(queryAllByTestId('reactified-link')).toHaveLength(0);
    });

    describe('routes with collaborators module', () => {
        const item1 = {
            key: 'subheader.accounting.collaboratorSplits',
            url: '/accounting/collaborators',
            module: 'frontend-collaborator',
        };
        const items = [item1];

        test('renders collaborators reactified links with beta badge', () => {
            const { getAllByTestId } = renderComponent({ items }, {}, true);
            expect(getAllByTestId('reactified-link')).toHaveLength(
                items.length
            );
        });
    });

    describe('filters routes non accesible to AWAL users', () => {
        beforeEach(() => {
            jest.spyOn(AppConfigModule, 'useAppConfig').mockReturnValue({
                ...mockAppConfig,
                brand: 'awal',
            });
        });

        const items = [
            { key: 'Item1', url: '/link1' },
            { key: 'Item2', url: '/link2' },
            { key: 'ItemM', url: '/marketing2' },
        ];

        test('does not render the marketing button', () => {
            const { getAllByTestId } = renderComponent({ items }, {}, true);
            expect(getAllByTestId('legacy-link')).toHaveLength(2);
        });
    });
});
