import { FC, useCallback, useState } from 'react';
import { Visible, Divider } from 'components';
import { Play, PlayDown } from 'icons';
import { TouchableTile } from 'components/touchable-tile';
import { Container, ScrollView, TouchableWithoutFeedback } from 'components/layout';
import { useProfile, useResponsiveLayout } from 'hooks';
import { MyProfileFragment, MyProfileFragmentDoc, useUpdateUserMutation } from 'expo-schema';
import { omit } from 'lodash';
import { PreferredEmail } from '../preferred-email';
import { Notifications } from '../notification';
import { Theme } from '../theme';
import { Timezone } from '../timezone';
import { Voice } from '../voice';
import { PaidMemberships } from '../paid-memberships';
import { Blocked } from '../blocked';

export const Root: FC = () => {
  const [openedItemId, setOpenedItemId] = useState(1);
  const { profile } = useProfile();
  const { isMobile } = useResponsiveLayout();

  const [updatePreferences] = useUpdateUserMutation({
    update: (cache, { data }) => {
      cache.modify({
        fields: {
          me() {
            const updatedPreferences = cache.writeFragment({
              data: data?.updateUser.user,
              fragment: MyProfileFragmentDoc,
              fragmentName: 'MyProfile',
            });
            return updatedPreferences;
          },
        },
      });
    },
  });
  const handleUpdate = useCallback(
    (incomingProfile: MyProfileFragment) => {
      const updateProfile = { ...incomingProfile };
      if (incomingProfile.pushNotificationPreference) {
        updateProfile.pushNotificationPreference = omit(
          incomingProfile.pushNotificationPreference,
          '__typename'
        );
      }

      if (incomingProfile.emailNotificationPreference) {
        updateProfile.emailNotificationPreference = omit(
          incomingProfile.emailNotificationPreference,
          '__typename'
        );
      }
      updatePreferences({
        variables: {
          input: {
            ...updateProfile,
            id: profile?.id as string,
          },
        },
        optimisticResponse: {
          updateUser: {
            __typename: 'UpdateUserPayload',
            user: {
              ...profile,
              __typename: 'User',
              // Incoming profile contains __typename which is required for optimistic mutations
              ...incomingProfile,
            } as MyProfileFragment,
          },
        },
      });
    },
    [profile, updatePreferences]
  );

  const settingsList = [
    {
      title: 'Change preferred email',
      component: () => <PreferredEmail handleUpdate={handleUpdate} />,
      id: 1,
    },
    {
      title: 'Change push notifications preference',
      component: () => <Notifications variant="push" handleUpdate={handleUpdate} />,
      id: 2,
    },
    {
      title: 'Change email notifications preference',
      component: () => <Notifications variant="email" handleUpdate={handleUpdate} />,
      id: 3,
    },
    {
      title: 'Change timezone',
      component: () => <Timezone handleUpdate={handleUpdate} />,
      id: 4,
    },

    {
      title: 'Change Theme',
      component: () => <Theme />,
      id: 5,
    },
    {
      title: 'Voice Settings',
      component: () => <Voice />,
      id: 6,
    },
    {
      title: 'Paid Memberships',
      component: () => <PaidMemberships />,
      id: 7,
    },
    {
      title: 'Blocked Users',
      component: () => <Blocked />,
      id: 8,
    },
  ];

  const isOpened = useCallback(
    (id) => {
      return id === openedItemId;
    },
    [openedItemId]
  );

  const renderArrow = useCallback(
    (id) => {
      if (id === openedItemId) {
        return <PlayDown colorVariant="title" width={10} height={10} />;
      } else {
        return <Play width={10} height={10} />;
      }
    },
    [openedItemId]
  );

  const isLineVisible = useCallback(
    (index) => {
      return settingsList.length > index + 1;
    },
    [settingsList.length]
  );

  const handleToggle = useCallback(
    (id) => {
      if (openedItemId === id) {
        setOpenedItemId(0);
      } else {
        setOpenedItemId(id);
      }
    },
    [openedItemId]
  );

  const height = isMobile ? undefined : 560;

  return (
    <TouchableWithoutFeedback onPress={() => {}}>
      <Container height={height}>
        <ScrollView px="l">
          {settingsList.map(({ id, title, component }, index) => {
            return (
              <Container key={id} flexShrink={1}>
                <TouchableTile
                  shapeVariant="square"
                  variant="text"
                  underlayColor={'transparent'}
                  onPress={() => handleToggle(id)}
                  height={62}
                  leftElement={renderArrow(id)}
                  title={title}
                  titleVariant="body"
                  titleColor="caption"
                />
                <Visible if={isOpened(id)}>{component()}</Visible>
                <Visible if={isLineVisible(index)}>
                  <Divider colorVariant="divider-02" />
                </Visible>
              </Container>
            );
          })}
        </ScrollView>
      </Container>
    </TouchableWithoutFeedback>
  );
};
