import type { FC } from 'react';
import React, { useCallback, useEffect, useRef, useState } from 'react';
import { Text, View } from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import {
    createNavigationContainerRef,
    type ParamListBase
} from '@react-navigation/native';
import {
    BottomSheetModal,
    type BottomSheetBackdropProps
} from '@gorhom/bottom-sheet';
import { bottomSheetHeaderAppliedFilters } from '../../apollo/reactive-vars';
import { spacing, useTheme } from '../../branding';
import type { BottomSheetProps, FilterProps } from './types';
import Backdrop from './Backdrop';
import Header from './Header';
import BottomSheetNavigator from './BottomSheetNavigator';
import themedStyles from './styles';
import HeaderTitleWithFilterCount from './HeaderTitleWithFilterCount';
import TouchableOpacity from '../../components/TouchableOpacity';
import { BOTTOM_SHEET_ELEMENTS_ALIGNMENT } from './constants';
import type { FilterScreenValue } from '../../apollo/reactive-vars/bottom-sheet-header-applied-filters';

export const BottomSheet: FC<BottomSheetProps> = ({
    title,
    isVisible,
    onClose,
    screens,
    titleAlign = BOTTOM_SHEET_ELEMENTS_ALIGNMENT.left,
    showCloseButton = true,
    closeButtonAlign = BOTTOM_SHEET_ELEMENTS_ALIGNMENT.right,
    enableOverDrag = true,
    enableDynamicSizing = true,
    snapPoints = [],
    footerButtons = [],
    showFooterButtons = false,
    onGoBack = () => {},
    enableContentPanningGesture = true
}) => {
    const { theme } = useTheme();
    const styles = themedStyles[theme];
    const { bottom: safeAreaBottom } = useSafeAreaInsets();
    const modalRef = useRef<BottomSheetModal>(null);
    const navigationRef = useRef(createNavigationContainerRef<ParamListBase>());
    const initialScreenName = screens?.[0]?.name || '';
    const initialScreenTitle = screens?.[0]?.options?.title || '';
    const [activeRouteName, setActiveRouteName] =
        useState<string>(initialScreenName);
    const [activeRouteTitle, setActiveRouteTitle] = useState<string>(
        initialScreenTitle as string
    );
    const showBackButton = Boolean(
        activeRouteName &&
            initialScreenName &&
            activeRouteName !== initialScreenName
    );
    const displayFooterButtons = showFooterButtons && footerButtons.length;
    const [isSettledOpen, setIsSettledOpen] = useState(false);

    useEffect(() => {
        if (isVisible) {
            modalRef.current?.present();
        } else {
            modalRef.current?.dismiss();
        }
    }, [isVisible]);

    const handleOnChange = (index: number) => {
        setIsSettledOpen(index >= 0);
        if (index === -1) {
            setActiveRouteName(initialScreenName);
            setActiveRouteTitle(initialScreenTitle as string);
            onClose();
        }
    };

    const renderBackdrop = useCallback(
        (backdropProps: BottomSheetBackdropProps) => (
            <Backdrop
                {...backdropProps}
                pressBehavior={isSettledOpen ? 'close' : 'none'}
            />
        ),
        [isSettledOpen]
    );

    const handleGoBack = () => {
        const navigation = navigationRef.current;
        const routFilters =
            bottomSheetHeaderAppliedFilters()[activeRouteName] || [];
        onGoBack(activeRouteName, routFilters);
        navigation.goBack();
    };

    const handleRouteChange = (routeName: string) => {
        setActiveRouteName(routeName);

        const nextTitle = screens.find(screen => screen.name === routeName)
            ?.options?.title;
        setActiveRouteTitle(nextTitle as string);
    };

    const handlePressFooterButton = (
        onPress: (
            routeName: string,
            currentScreenFilters: FilterScreenValue[],
            filters: FilterProps
        ) => void
    ) => {
        const filters = bottomSheetHeaderAppliedFilters();
        const currentScreenFilters = filters[activeRouteName] || [];
        onPress(activeRouteName, currentScreenFilters, filters);
    };

    return (
        <BottomSheetModal
            ref={modalRef}
            enableDynamicSizing={enableDynamicSizing}
            backdropComponent={renderBackdrop}
            onChange={handleOnChange}
            backgroundStyle={styles.bottomSheetBackground}
            handleStyle={styles.handle}
            handleIndicatorStyle={styles.indicator}
            enableOverDrag={enableOverDrag}
            snapPoints={snapPoints}
            enableContentPanningGesture={enableContentPanningGesture}
            keyboardBehavior="interactive"
            keyboardBlurBehavior="restore"
            android_keyboardInputMode="adjustResize"
        >
            <View style={styles.content}>
                <View style={styles.body}>
                    <Header
                        title={
                            <HeaderTitleWithFilterCount
                                title={title}
                                onBack={handleGoBack}
                                showBackButton={showBackButton}
                                activeRouteTitle={activeRouteTitle}
                                activeRouteName={activeRouteName}
                            />
                        }
                        onBottomSheetClose={onClose}
                        titleAlign={titleAlign}
                        showCloseButton={showCloseButton}
                        closeButtonAlign={closeButtonAlign}
                    />
                    <View style={styles.navigationContainer}>
                        <BottomSheetNavigator
                            navigationRef={navigationRef}
                            screens={screens}
                            onRouteChange={handleRouteChange}
                        />
                    </View>
                </View>
                {displayFooterButtons ? (
                    <View
                        testID="bottomSheetFooterContainer"
                        style={[
                            styles.footerContainer,
                            {
                                paddingBottom: spacing.ml + safeAreaBottom
                            }
                        ]}
                    >
                        {footerButtons.map(({ title, color, onPress }) => (
                            <TouchableOpacity
                                key={`${title}-${title}`}
                                testID={`bottomSheetFooterButton-${title}`}
                                accessibilityLabel={title}
                                onPress={() => handlePressFooterButton(onPress)}
                                style={[
                                    styles.footerButton,
                                    { backgroundColor: color }
                                ]}
                            >
                                <Text
                                    style={styles.footerButtonText}
                                    numberOfLines={2}
                                >
                                    {title.toUpperCase()}
                                </Text>
                            </TouchableOpacity>
                        ))}
                    </View>
                ) : null}
            </View>
        </BottomSheetModal>
    );
};

export default BottomSheet;
