// GO-4704: Tests for BottomSheet footer padding behaviour.
// The footer paddingBottom changed from Math.max(safeAreaBottom, spacing.ml) to
// spacing.ml + safeAreaBottom, and styles.ts gained paddingBottom: spacing.ml in
// the footerContainer block. These tests verify the footer is rendered with the
// correct accessibility labels under varying safeAreaBottom values.

import React from 'react';
import { render, screen } from '@testing-library/react-native';
import { BottomSheetModalProvider } from '@gorhom/bottom-sheet';
import { BottomSheet } from '../BottomSheet';
import useTheme from '../../../branding/hooks/useTheme';
import themes from '../../../branding/themes';
import { BASE_THEME } from '../../../branding/constants/themes';
import { spacing } from '../../../branding/utils/spacing';

jest.mock('@gorhom/bottom-sheet', () => require('@gorhom/bottom-sheet/mock'));

const mockUseSafeAreaInsets = jest.fn();

jest.mock('react-native-safe-area-context', () => ({
    useSafeAreaInsets: () => mockUseSafeAreaInsets()
}));

jest.mock('../BottomSheetNavigator', () => ({
    __esModule: true,
    default: () => null
}));

jest.mock('../../../branding/hooks/useTheme', () => ({
    __esModule: true,
    default: jest.fn()
}));

jest.mock('../../../apollo/reactive-vars', () => ({
    bottomSheetHeaderAppliedFilters: {}
}));

jest.mock('@apollo/client', () => ({
    useReactiveVar: () => ({})
}));

const mockUseTheme = useTheme as jest.MockedFunction<typeof useTheme>;

const ScreenComponent = () => <React.Fragment />;

const defaultProps = {
    title: 'Test sheet',
    isVisible: true,
    onClose: jest.fn(),
    screens: [{ name: 'main', component: ScreenComponent }]
};

const withFooterProps = {
    ...defaultProps,
    showFooterButtons: true,
    footerButtons: [
        {
            title: 'Apply',
            color: '#ffffff',
            onPress: jest.fn()
        }
    ]
};

const renderBottomSheet = (props: React.ComponentProps<typeof BottomSheet>) =>
    render(
        <BottomSheetModalProvider>
            <BottomSheet {...props} />
        </BottomSheetModalProvider>
    );

describe('BottomSheet', () => {
    beforeEach(() => {
        mockUseSafeAreaInsets.mockReturnValue({
            top: 0,
            bottom: 0,
            left: 0,
            right: 0
        });
        mockUseTheme.mockImplementation(() => ({
            ...themes[BASE_THEME],
            theme: BASE_THEME,
            setTheme: jest.fn()
        }));
    });

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

    describe('footer visibility', () => {
        it('does not render footer buttons when showFooterButtons is false', () => {
            renderBottomSheet({
                ...defaultProps,
                showFooterButtons: false,
                footerButtons: [
                    { title: 'Apply', color: '#fff', onPress: jest.fn() }
                ]
            });

            expect(screen.queryByLabelText('Apply')).toBeNull();
        });

        it('does not render footer buttons when footerButtons is empty', () => {
            renderBottomSheet({
                ...defaultProps,
                showFooterButtons: true,
                footerButtons: []
            });

            expect(screen.queryByLabelText('Apply')).toBeNull();
        });

        it('renders footer buttons when showFooterButtons is true and footerButtons is non-empty', () => {
            renderBottomSheet(withFooterProps);

            expect(screen.getByLabelText('Apply')).toBeTruthy();
        });

        it('renders all provided footer buttons', () => {
            renderBottomSheet({
                ...defaultProps,
                showFooterButtons: true,
                footerButtons: [
                    { title: 'Apply', color: '#fff', onPress: jest.fn() },
                    { title: 'Reset', color: '#000', onPress: jest.fn() }
                ]
            });

            expect(screen.getByLabelText('Apply')).toBeTruthy();
            expect(screen.getByLabelText('Reset')).toBeTruthy();
        });

        it('applies paddingBottom of spacing.ml + safeAreaBottom when bottom inset is non-zero', () => {
            mockUseSafeAreaInsets.mockReturnValue({
                top: 0,
                bottom: 48,
                left: 0,
                right: 0
            });

            renderBottomSheet(withFooterProps);

            const footerContainer = screen.getByTestId(
                'bottomSheetFooterContainer'
            );
            expect(footerContainer.props.style).toMatchObject([
                expect.anything(),
                { paddingBottom: spacing.ml + 48 }
            ]);
        });
    });

    describe('footer button labels', () => {
        it('renders the button label in uppercase text', () => {
            renderBottomSheet(withFooterProps);

            expect(screen.getByText('APPLY')).toBeTruthy();
        });
    });

    describe('snapshot', () => {
        it('matches snapshot with footer buttons visible', () => {
            renderBottomSheet(withFooterProps);

            expect(screen.toJSON()).toMatchSnapshot();
        });

        it('matches snapshot without footer buttons', () => {
            renderBottomSheet(defaultProps);

            expect(screen.toJSON()).toMatchSnapshot();
        });
    });
});
