import React from 'react';
import { render, fireEvent } from '@testing-library/react';
import * as AppConfigModule from '@theorchard/suite-frontend';
import { mockAppConfig } from 'lib/test-helpers/factories';
import { createIdentity } from 'lib/test-utils/identity-factory';
import { MemoryRouter } from 'react-router-dom';
import IdentityContext from 'src/context';
import HeaderBannerWithRouter, {
    ORCHARD_GO_BANNER,
    ORCHARD_GO_FEATURE_CONTROL,
    ORCHARD_GO_SURVEY_BANNER,
    ORCHARD_GO_SURVEY_FEATURE_CONTROL,
} from '../header-banner';

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

describe('<HeaderBanner>', () => {
    const renderComponent = (
        identity: ReturnType<typeof createIdentity>,
        pathname = '/'
    ) =>
        render(
            <MemoryRouter initialEntries={[pathname]}>
                <IdentityContext.Provider
                    value={{ identity, hasAuthentication: () => false }}
                >
                    <HeaderBannerWithRouter />
                </IdentityContext.Provider>
            </MemoryRouter>
        );

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

    describe('location is not permitted', () => {
        test('returns null', () => {
            const identity = createIdentity({});
            jest.spyOn(identity, 'hasFeatureFlag').mockReturnValue(false);
            const { container } = renderComponent(identity, '/test');
            expect(container.firstChild).toBeNull();
        });
    });

    describe('user is not authorized', () => {
        test('returns null', () => {
            const identity = createIdentity({ id: 1 });
            jest.spyOn(identity, 'hasPermission').mockReturnValue(false);
            jest.spyOn(identity, 'hasFeatureControl').mockReturnValue(false);
            jest.spyOn(identity, 'hasFeatureFlag').mockReturnValue(false);
            const { container } = renderComponent(identity);
            expect(container.firstChild).toBeNull();
        });
    });

    describe('Orchard GO Banner', () => {
        let identity: ReturnType<typeof createIdentity>;

        beforeEach(() => {
            identity = createIdentity({ id: 1 });
            jest.spyOn(identity, 'hasPermission').mockReturnValue(false);
            jest.spyOn(identity, 'hasFeatureControl').mockImplementation(
                feat => feat === ORCHARD_GO_FEATURE_CONTROL
            );
            jest.spyOn(identity, 'hasFeatureFlag').mockReturnValue(false);
            window.analytics = { track: jest.fn() };
        });

        afterEach(() => {
            delete window.analytics;
        });

        test('renders Orchard Go Banner', () => {
            const { container } = renderComponent(identity);
            expect(
                container.querySelector('.Orchard-go-ad')
            ).toBeInTheDocument();
        });

        test('dismissing banner sets cookie and calls analytics', () => {
            const { container } = renderComponent(identity);
            const closeBtn = container.querySelector(
                '.Advertising-banner-closeBannerButton'
            );
            if (closeBtn) fireEvent.click(closeBtn);
            expect(document.cookie).toContain(`${ORCHARD_GO_BANNER}=false`);
            expect(window.analytics?.track).toHaveBeenCalledWith('Dismissed', {
                category: 'Workstation Banner',
                label: ORCHARD_GO_BANNER,
            });
        });

        test('does not render if banner dismissed', () => {
            document.cookie = `${ORCHARD_GO_BANNER}=false`;
            const { container } = renderComponent(identity);
            expect(container.querySelector('.Orchard-go-ad')).toBeNull();
        });
    });

    describe('Orchard GO Survey Banner', () => {
        let identity: ReturnType<typeof createIdentity>;

        beforeEach(() => {
            identity = createIdentity({ id: 1 });
            jest.spyOn(identity, 'hasPermission').mockReturnValue(false);
            jest.spyOn(identity, 'hasFeatureControl').mockImplementation(
                feat => feat === ORCHARD_GO_SURVEY_FEATURE_CONTROL
            );
            jest.spyOn(identity, 'hasFeatureFlag').mockReturnValue(false);
            window.analytics = { track: jest.fn() };
        });

        afterEach(() => {
            delete window.analytics;
        });

        test('renders Orchard Go Survey Banner', () => {
            const { container } = renderComponent(identity);
            expect(
                container.querySelector('.Orchard-go-ad')
            ).toBeInTheDocument();
        });

        test('does not render if banner dismissed', () => {
            document.cookie = `${ORCHARD_GO_SURVEY_BANNER}=false`;
            const { container } = renderComponent(identity);
            expect(container.querySelector('.Orchard-go-ad')).toBeNull();
        });
    });
});
