import React, {useCallback, useMemo} from 'react';
import {ListRenderItem, View} from 'react-native';
import {useTranslation} from 'react-i18next';
import {QueryKey, useMutation, useQueryClient} from '@tanstack/react-query';
import {useNavigation} from '@react-navigation/native';
import {IconEdit, IconTargetArrow, IconTrash} from '@tabler/icons-react-native';
import {Dialog, List, ListRow, MenuProps, Typography} from '@components';
import {Goal, GoalStatus, MenuOption} from '@modules/goals/interfaces';
import {deleteGoal} from '@modules/goals/services';
import {useUserId} from '@redux/selectors';
import {showSnackbar} from '@redux/dispatchers';
import {Screens} from '@shared/constants';
import {isAndroid} from '@shared/utils';

import {styles} from './styles';

interface GoalOptionsMenuProps
  extends Omit<MenuProps<MenuOption>, 'renderItem' | 'data'> {
  targetGoal: Nullable<Goal>;
  setShowMenu: (show: boolean) => void;
  setShowDeleteModal: (show: boolean) => void;
  goalFlowEnabled?: boolean;
  showDeleteModal: boolean;
  queryKeyInvalidated: QueryKey;
}

const keyExtractor = (item: MenuOption) => item.key;

export function GoalOptionsMenu({
  targetGoal,
  setShowMenu,
  showDeleteModal,
  setShowDeleteModal,
  goalFlowEnabled,
  queryKeyInvalidated,
  title,
  ...props
}: GoalOptionsMenuProps) {
  const {t} = useTranslation();
  const navigation = useNavigation();
  const userId = useUserId();
  const queryClient = useQueryClient();

  const canEdit = useMemo(
    () =>
      !goalFlowEnabled ||
      (targetGoal?.status === GoalStatus.IN_PROGRESS &&
        !targetGoal?.goalOwners.some(owner => owner.userId === userId)) ||
      targetGoal?.status === GoalStatus.DRAFT,
    [goalFlowEnabled, targetGoal?.goalOwners, targetGoal?.status, userId],
  );

  const menuOptions: MenuOption[] = useMemo(() => {
    const baseOptions: MenuOption[] = [
      {
        key: 'view',
        label: t('goals.list.menu.view'),
        LeftIcon: IconTargetArrow,
      },
    ];

    return canEdit
      ? [
          ...baseOptions,
          {
            key: 'edit',
            label: t('goals.list.menu.edit'),
            LeftIcon: IconEdit,
          },
          {
            key: 'delete',
            label: t('goals.list.menu.delete'),
            LeftIcon: IconTrash,
          },
        ]
      : baseOptions;
  }, [canEdit, t]);

  const onMenuItemPress = useCallback(
    (key: string) => () => {
      switch (key) {
        case 'edit':
          setShowMenu(false);
          targetGoal &&
            navigation.navigate(Screens.EDIT_GOAL, {
              id: targetGoal.id,
              ownerUserId: targetGoal?.goalOwners[0]?.ownerUser?.userId,
            });
          break;
        case 'delete':
          setShowDeleteModal(true);
          break;
        case 'view':
        default:
          setShowMenu(false);
          targetGoal &&
            navigation.navigate(Screens.GOAL_DETAIL, {id: targetGoal.id});
          break;
      }
    },
    [navigation, setShowDeleteModal, setShowMenu, targetGoal],
  );

  const renderItem: ListRenderItem<MenuOption> = ({item}) => (
    <ListRow onPress={onMenuItemPress(item.key)}>
      <ListRow.Avatar Icon={item.LeftIcon} />
      <ListRow.Title title={item.label} />
      <ListRow.SideContent withRightIcon />
    </ListRow>
  );

  const {mutate, isPending} = useMutation({
    mutationFn: deleteGoal,
    onSuccess: () => {
      queryClient.invalidateQueries({queryKey: queryKeyInvalidated});
      setShowDeleteModal(false);
      showSnackbar({
        title: t('goals.delete.success'),
        variant: 'success',
      });
    },
  });

  const onClose = () => {
    setShowMenu(false);
    setShowDeleteModal(false);
  };

  const onConfirm = () => {
    targetGoal?.id && mutate(targetGoal.id);
    onClose();
  };

  const primaryButton = {
    text: t('general.delete'),
    onPress: onConfirm,
    isLoading: isPending,
  };

  const secondaryButton = {
    text: t('general.cancel'),
    onPress: onClose,
    isLoading: isPending,
  };

  const onGoBack = () => setShowDeleteModal(false);

  const index = useMemo(
    () => (showDeleteModal && isAndroid ? 2 : menuOptions.length > 1 ? 1 : 0),
    [showDeleteModal, menuOptions.length],
  );

  return (
    <Dialog
      {...props}
      snapPoints={['20%', '32%', '37%']}
      index={index}
      title={showDeleteModal ? t('goals.delete.description') : title}
      titleNumberOfLines={2}
      onClose={onClose}
      withCloseButton={!showDeleteModal}
      onGoBack={onGoBack}
      footer={
        showDeleteModal
          ? {
              primaryButton,
              secondaryButton,
            }
          : undefined
      }>
      {showDeleteModal ? (
        <View style={styles.deleteDescription}>
          <Typography align="center">{t('goals.delete.warning')}</Typography>
        </View>
      ) : (
        <List
          data={menuOptions}
          renderItem={renderItem}
          keyExtractor={keyExtractor}
          style={styles.list}
        />
      )}
    </Dialog>
  );
}
