import React from 'react';
import { fireEvent, screen, waitFor } from '@testing-library/react';
import { FlattenedApolloError, Segment } from '@theorchard/suite-frontend';
import { renderInAppContext } from '@theorchard/suite-testing';
import { getMergedProduct, getProductMetadata } from 'lib/mockProductData';
import * as features from 'src/utils/features';
import FullscreenModalReview from '../fullscreenModalReview';
import { Props } from '../fullscreenModalReview';

describe('<FullscreenModalReview>', () => {
    const defaultProps: Props = {
        product: getProductMetadata(),
        mergedProduct: getMergedProduct(),
        isProductAndQueueItemLoaded: true,
        isLoadingItemsOrProduct: false,
        productQueryError: undefined,
        isOpen: true,
        submissionType: undefined,
        onClickSkip: jest.fn(),
        onClose: jest.fn(),
        renderModalBody: jest.fn(),
        queueName: 'initial',
        isApprovalNoteRequired: false,
        isApprovalBlocked: false,
        isRejectionBlocked: false,
        isSubmittingReview: false,
        isReviewHistoryDisabled: false,
        productReviewQueueId: 1,
        onReviewCompleted: jest.fn(),
        onQueueMove: jest.fn(),
        productTargetGroup: null,
        submittedByUserLanguage: null,
        currentReviewQueueItemId: 111,
        lockedByUserName: undefined,
        wasExistingLockDetected: false,
    };

    const render = (customProps?: Partial<Props>) =>
        renderInAppContext(
            <FullscreenModalReview {...defaultProps} {...customProps} />
        );

    describe('skip button', () => {
        test('skip enabled - not loading/ no errors', () => {
            const { getByTestId } = render();
            expect(getByTestId('skip-button')).toBeEnabled();
        });

        test('skip enabled - loading and has errors', () => {
            const { getByTestId } = render({
                isLoadingItemsOrProduct: true,
                productQueryError: { message: 'error' } as FlattenedApolloError,
            });
            expect(getByTestId('skip-button')).toBeEnabled();
        });

        test('skip enabled - not loading and has errors', () => {
            const { getByTestId } = render({
                isLoadingItemsOrProduct: false,
                productQueryError: { message: 'error' } as FlattenedApolloError,
            });
            expect(getByTestId('skip-button')).toBeEnabled();
        });

        test('skip disabled - loading/ no errors', () => {
            const { getByTestId } = render({
                isLoadingItemsOrProduct: true,
            });
            expect(getByTestId('skip-button')).toBeDisabled();
        });
    });

    describe('useDisplayProductModalPageHeaderFF', () => {
        beforeEach(() => {
            const mockIntersectionObserver = jest.fn();
            mockIntersectionObserver.mockReturnValue({
                observe: () => null,
                unobserve: () => null,
                disconnect: () => null,
            });
            window.IntersectionObserver = mockIntersectionObserver;
        });

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

        test('renders ProductModalHeaderV2 when feature flag is disabled', () => {
            jest.spyOn(
                features,
                'useDisplayProductModalPageHeaderFF'
            ).mockReturnValue(false);
            const { getAllByTestId, queryByTestId } = render();

            // ProductModalHeaderV2 should be rendered
            const headerV2Elements = getAllByTestId('ProductModalHeaderV2');
            expect(headerV2Elements.length).toBeGreaterThan(0);

            // ProductModalHeader should not be rendered
            expect(queryByTestId('ProductModalHeader')).not.toBeInTheDocument();
        });

        test('renders ProductModalHeader when feature flag is enabled', () => {
            jest.spyOn(
                features,
                'useDisplayProductModalPageHeaderFF'
            ).mockReturnValue(true);
            const { getAllByTestId, queryByTestId } = render();

            // ProductModalHeader should be rendered
            const headerElements = getAllByTestId('ProductModalHeader');
            expect(headerElements.length).toBeGreaterThan(0);

            // ProductModalHeaderV2 should not be rendered
            expect(
                queryByTestId('ProductModalHeaderV2')
            ).not.toBeInTheDocument();
        });

        test('does not render any header when product is not loaded', () => {
            jest.spyOn(
                features,
                'useDisplayProductModalPageHeaderFF'
            ).mockReturnValue(false);
            const { queryByTestId } = render({
                isProductAndQueueItemLoaded: false,
                product: null,
                mergedProduct: null,
            });

            expect(
                queryByTestId('ProductModalHeaderV2')
            ).not.toBeInTheDocument();
            expect(queryByTestId('ProductModalHeader')).not.toBeInTheDocument();
        });
    });

    describe('product review history', () => {
        test('renders sidebar', async () => {
            const { getByTestId } = render();
            expect(getByTestId('SuiteSidebarPortal')).toBeInTheDocument();
        });

        test('on click, opens and displays product review history', async () => {
            const { getByTestId, queryByTestId } = render();

            expect(getByTestId('SuiteSidebarPortal')).toBeInTheDocument();
            const reviewHistoryButton = getByTestId('review-history-button');
            expect(reviewHistoryButton).toBeInTheDocument();
            expect(reviewHistoryButton).toBeEnabled();

            expect(
                screen.queryByText('Review History')
            ).not.toBeInTheDocument();
            expect(queryByTestId('Stepper')).not.toBeInTheDocument();
            fireEvent.click(reviewHistoryButton);

            expect(await screen.findByText('Review History')).toBeVisible();
            expect(await screen.findByText('Submitted')).toBeVisible();
            expect(await screen.findByText('Approved')).toBeVisible();
            expect(
                await screen.findByText('14 Nov 2024 by User ABC')
            ).toBeVisible();
            expect(await screen.findByText('14 May 2024')).toBeVisible();
            expect(
                await screen.findByText('Escalation Type: Example Type 1')
            ).toBeVisible();
            expect(getByTestId('Stepper')).toBeVisible();
        });

        test('renders note as step body', () => {
            const { getByTestId, getAllByTestId } = render();

            expect(getByTestId('SuiteSidebarPortal')).toBeInTheDocument();

            const reviewHistoryButton = getByTestId('review-history-button');
            expect(reviewHistoryButton).toBeEnabled();
            fireEvent.click(reviewHistoryButton);

            const expandableContent = getAllByTestId('ExpandableContent')[1];
            expect(expandableContent).toBeInTheDocument();

            const label = expandableContent.querySelector(
                '.ExpandableContent-label'
            );
            expect(label).toBeInTheDocument();
            expect(label).toHaveTextContent('See Notes');

            const body = expandableContent.querySelector(
                '.ExpandableContent-content'
            );
            expect(body).toBeInTheDocument();
            expect(body).toHaveTextContent(
                'there is something wrong, take a look'
            );
        });

        test('closes sidebar upon rerender for a different product', async () => {
            const { rerender, getByTestId, queryByText } = render();
            const reviewHistoryButton = getByTestId('review-history-button');
            await waitFor(() => {
                expect(reviewHistoryButton).toBeEnabled();
            });
            expect(queryByText('Review History')).toBeNull();
            fireEvent.click(reviewHistoryButton);
            expect(queryByText('Review History')).toBeVisible();
            rerender(
                <FullscreenModalReview
                    {...defaultProps}
                    productReviewQueueId={2}
                />
            );
            expect(queryByText('Review History')).toBeNull();
        });

        describe('track events via segment - review history', () => {
            const segmentTrack = jest.spyOn(Segment, 'trackEvent');
            beforeEach(() => segmentTrack.mockClear());

            test('track click event - open/ close review history', () => {
                let timestamp = Date.now();
                jest.useFakeTimers().setSystemTime(timestamp);
                const { getByTestId } = render({
                    product: getProductMetadata({ releaseCorrection: null }),
                    mergedProduct: getMergedProduct({
                        releaseCorrection: null,
                    }),
                });

                const reviewHistoryButton = getByTestId(
                    'review-history-button'
                );
                expect(reviewHistoryButton).toBeEnabled();
                fireEvent.click(reviewHistoryButton);

                expect(segmentTrack).toHaveBeenCalledWith(
                    'Click',
                    {
                        accountId: 123,
                        productId: 33,
                        subaccountId: 333,
                        category: 'Content Review Digital Audio',
                        value: timestamp,
                        label: 'Open History',
                    },
                    'Open History'
                );
                const historySidebar = getByTestId(
                    'ProductReviewHistorySidebar'
                );
                expect(historySidebar).toBeInTheDocument();

                segmentTrack.mockClear();
                timestamp = Date.now();
                jest.useFakeTimers().setSystemTime(timestamp);

                const closeButton =
                    historySidebar.querySelector('.btn-control');
                if (closeButton) {
                    fireEvent.click(closeButton);
                }
                expect(segmentTrack).toHaveBeenCalledWith(
                    'Click',
                    {
                        accountId: 123,
                        productId: 33,
                        subaccountId: 333,
                        category: 'Content Review Digital Audio',
                        value: timestamp,
                        label: 'Close History',
                    },
                    'Close History'
                );
            });

            test('track click event - notes toggle', () => {
                const { getByTestId, getAllByTestId } = render({
                    product: getProductMetadata({ releaseCorrection: null }),
                    mergedProduct: getMergedProduct({
                        releaseCorrection: null,
                    }),
                });

                const reviewHistoryButton = getByTestId(
                    'review-history-button'
                );
                expect(reviewHistoryButton).toBeEnabled();
                fireEvent.click(reviewHistoryButton);

                segmentTrack.mockClear();
                let timestamp = Date.now();
                jest.useFakeTimers().setSystemTime(timestamp);

                const expandableContent =
                    getAllByTestId('ExpandableContent')[0];
                expect(expandableContent).toBeInTheDocument();

                const toggleComponent = expandableContent.querySelector('div');
                if (toggleComponent) fireEvent.click(toggleComponent);
                expect(segmentTrack).toHaveBeenCalledWith(
                    'Click',
                    {
                        accountId: 123,
                        category: 'Content Review Digital Audio',
                        label: 'See Approval Notes',
                        productId: 33,
                        subaccountId: 333,
                        value: timestamp,
                    },
                    'See Approval Notes'
                );
                segmentTrack.mockClear();
                timestamp = Date.now();
                jest.useFakeTimers().setSystemTime(timestamp);
                if (toggleComponent) fireEvent.click(toggleComponent);
                expect(segmentTrack).toHaveBeenCalledWith(
                    'Click',
                    {
                        accountId: 123,
                        category: 'Content Review Digital Audio',
                        label: 'Close Approval Notes',
                        productId: 33,
                        subaccountId: 333,
                        value: timestamp,
                    },
                    'Close Approval Notes'
                );
            });

            test('track click event - move notes', () => {
                const { getByTestId, getAllByTestId } = render({
                    product: getProductMetadata({ releaseCorrection: null }),
                    mergedProduct: getMergedProduct({
                        releaseCorrection: null,
                    }),
                });

                const reviewHistoryButton = getByTestId(
                    'review-history-button'
                );
                expect(reviewHistoryButton).toBeEnabled();
                fireEvent.click(reviewHistoryButton);

                segmentTrack.mockClear();
                const timestamp = Date.now();
                jest.useFakeTimers().setSystemTime(timestamp);

                const expandableContent =
                    getAllByTestId('ExpandableContent')[1];
                expect(expandableContent).toBeInTheDocument();

                const toggleComponent = expandableContent.querySelector('div');
                if (toggleComponent) fireEvent.click(toggleComponent);
                expect(segmentTrack).toHaveBeenCalledWith(
                    'Click',
                    {
                        accountId: 123,
                        category: 'Content Review Digital Audio',
                        label: 'See Move Notes',
                        productId: 33,
                        queueName: 'escalation',
                        subaccountId: 333,
                        value: timestamp,
                    },
                    'See Move Notes'
                );
            });
        });
    });

    describe('product under review modal messaging', () => {
        jest.spyOn(features, 'useLockedProductError').mockReturnValue(true);

        test('renders product under review error message', () => {
            const { getByTestId } = render({
                lockedByUserName: 'reviewer',
                wasExistingLockDetected: true,
            });
            expect(
                getByTestId('review-queue-item-locked-state')
            ).toBeInTheDocument();
        });
        test('does not render locked state when product is not loaded', () => {
            const { queryByTestId } = render({
                lockedByUserName: 'reviewer',
                wasExistingLockDetected: true,
                isProductAndQueueItemLoaded: false,
            });
            expect(
                queryByTestId('review-queue-item-locked-state')
            ).not.toBeInTheDocument();
        });
        test('does not render product under review error message if item not locked', () => {
            const { queryByTestId } = render({
                lockedByUserName: 'reviewer',
                wasExistingLockDetected: false,
            });
            expect(
                queryByTestId('review-queue-item-locked-state')
            ).not.toBeInTheDocument();
        });
        test('renders "Return to Queue" button and navigates on click', () => {
            render({
                lockedByUserName: 'reviewer',
                wasExistingLockDetected: true,
            });
            const returnButton = screen.getByRole('link', {
                name: /Return to Queue/i,
            });
            expect(returnButton).toBeInTheDocument();
            expect(returnButton).toHaveAttribute('href', '/review-queue');
        });
    });
});
