/**
 * TODO: use `KeyboardStickyView` instead of custom animation when keyboard-controller is active globally
 */
import React, {memo, useCallback, useMemo} from 'react';
import {useDispatch} from 'react-redux';
import Animated, {
  makeMutable,
  SharedValue,
  useAnimatedStyle,
  useDerivedValue,
} from 'react-native-reanimated';
import {Portal} from '@gorhom/portal';
import {useReanimatedKeyboardAnimation} from 'react-native-keyboard-controller';
import {useSafeAreaBottomPadding} from '@hooks/useSafeAreaBottomPadding';
import {setLastEventEmitted, removeSnackbarItem} from '@redux/events';
import {useAppSelector} from '@redux/utils';

import {Snackbar} from '../Snackbar';
import {styles} from './styles';

export const snackbarSharedOffset: SharedValue<number> = makeMutable(0);

interface SnackbarStackProps {
  hostName?: string;
}

function SnackbarStack({hostName = 'root'}: SnackbarStackProps = {}) {
  const dispatch = useDispatch();
  const bottom = useSafeAreaBottomPadding();
  const {height} = useReanimatedKeyboardAnimation();
  const allSnackbars = useAppSelector(({events}) => events.snackbar.stack);
  const stack = useMemo(
    () => allSnackbars.filter(item => item.hostName === hostName),
    [allSnackbars, hostName],
  );

  const onActionPress = useCallback(
    (eventName?: string) => () => {
      eventName && dispatch(setLastEventEmitted(eventName));
    },
    [dispatch],
  );

  const onItemClose = useCallback(
    (id: string) => () => {
      dispatch(removeSnackbarItem(id));
    },
    [dispatch],
  );

  const bottomValue = useDerivedValue(() => {
    return snackbarSharedOffset.value !== 0
      ? snackbarSharedOffset.value - Math.min(height.value + bottom, 0) // height.value is negative
      : bottom;
  });

  const animatedStyle = useAnimatedStyle(() => {
    return {
      bottom: bottomValue.value,
    };
  });

  return (
    <Portal hostName={hostName}>
      <Animated.View style={[styles.container, animatedStyle]}>
        {stack.map(item => {
          return (
            <Snackbar
              key={item.id}
              title={item.title}
              description={item.description}
              variant={item.variant}
              actionLabel={item.action?.label}
              onActionPress={onActionPress(item.action?.eventName)}
              onClose={onItemClose(item.id)}
            />
          );
        })}
      </Animated.View>
    </Portal>
  );
}

const MemorizedSnackbarStack = memo(SnackbarStack);
export {MemorizedSnackbarStack as SnackbarStack};
