import React from 'react';
import { fireEvent, waitFor, screen } from '@testing-library/react';
import { SuiteLogger } from '@theorchard/suite-utils';
import { renderInAppContextLite } from '../../../../lib/test-utils/render';
import * as idtNotifsQuery from '../../../queries/identityNotifications';
import Segment from '../../../segment';
import { NotificationBanner } from '../notificationBanner';
import type { SuiteNotification } from '../../../types/notifications';

vi.mock('../../../queries/identityNotifications', () => ({
    useIdentityBankingNotificationsQuery: vi.fn(),
}));

const suiteNotifs: SuiteNotification[] = [
    {
        id: 'account-missing-tax-data',
        message: '<strong>Reminder:</strong> you need to provide your banking info...',
        variant: 'warn',
        link: 'https://documents.qaorch.com',
        linkText: 'Go to Banking & Tax',
    },
];

describe('<NotificationBanner>', () => {
    const renderComponent = () => renderInAppContextLite(<NotificationBanner />);

    beforeAll(() => {
        vi.spyOn(Segment, 'trackEvent').mockImplementation();
    });

    afterEach(() => {
        vi.resetAllMocks();
    });

    describe('identity has no notifications', () => {
        vi.spyOn(idtNotifsQuery, 'useIdentityBankingNotificationsQuery').mockReturnValue({
            loading: false,
            error: undefined,
            data: undefined,
        });

        test('renders nothing', () => {
            const { container } = renderComponent();
            expect(container).toBeEmptyDOMElement();
        });
    });

    describe('identity has notifications', () => {
        beforeEach(() => {
            vi.spyOn(idtNotifsQuery, 'useIdentityBankingNotificationsQuery').mockReturnValue({
                loading: false,
                error: undefined,
                data: suiteNotifs,
            });
        });

        test('renders the banner with the correct content', () => {
            const r = renderComponent();

            const banner = r.container.firstChild;
            const notifAlert = r.getByTestId('NotificationBanner-Alert');
            const parsedEl = notifAlert?.querySelector('strong');
            const btn = notifAlert.querySelector('button');

            expect(banner).toHaveClass('NotificationBanner');
            expect(notifAlert).toHaveClass('Alert-warn');
            expect(parsedEl?.textContent).toBe('Reminder:');
            expect(btn).toHaveTextContent(suiteNotifs[0].linkText!);
        });

        test('opens the link in a new tab when button is clicked', () => {
            const openSpy = vi.spyOn(window, 'open').mockImplementation(() => null);
            renderComponent();

            fireEvent.click(screen.getByRole('button', { name: suiteNotifs[0].linkText }));
            expect(openSpy).toHaveBeenCalledWith(suiteNotifs[0].link, '_blank');
        });

        test('sends a "Notification Shown" once per notification', async () => {
            renderComponent();

            await waitFor(() => {
                expect(Segment.trackEvent).toHaveBeenCalledTimes(1);
            });

            suiteNotifs.forEach((suiteNotif) => {
                expect(Segment.trackEvent).toHaveBeenCalledWith('Notification Shown', {
                    shownAs: 'banner',
                    id: suiteNotif.id,
                });
            });
        });

        describe('render multiple notifications', () => {
            const mockNotifs = [
                ...suiteNotifs,
                {
                    id: 'missing-surname',
                    message: 'notification_missing-identity-surname__message',
                    variant: 'information' as const,
                    __typename: 'SuiteNotification',
                    link: undefined,
                },
            ];

            beforeEach(() => {
                vi.spyOn(idtNotifsQuery, 'useIdentityBankingNotificationsQuery').mockReturnValue({
                    loading: false,
                    error: undefined,
                    data: mockNotifs,
                });
            });

            test('renders each banner of a different type', () => {
                const r = renderComponent();

                const notifAlerts = r.getAllByTestId('NotificationBanner-Alert');

                const notifAlertWarnBtn = notifAlerts[0].querySelector('button');
                const notifAlertInfoBtn = notifAlerts[1].querySelector('button');

                expect(notifAlerts[0]).toHaveClass('Alert-warn');
                expect(notifAlerts[1]).toHaveClass('Alert-information');

                expect(notifAlertWarnBtn).toHaveTextContent(suiteNotifs[0].linkText!);
                expect(notifAlertInfoBtn).toBeNull(); // no link, no button
            });
        });
    });

    describe('query returned an error', () => {
        beforeEach(() => {
            vi.spyOn(idtNotifsQuery, 'useIdentityBankingNotificationsQuery').mockReturnValue({
                loading: false,
                error: new Error('XYZ error'),
                data: undefined,
            });
        });

        test('renders nothing and logs via SuiteLogger', () => {
            const { container } = renderComponent();

            expect(container).toBeEmptyDOMElement();
            expect(SuiteLogger.error).toHaveBeenCalledWith('NotificationBanner', 'XYZ error');
        });
    });
});
