import React, { useCallback } from 'react';
import { Card, TouchableTile, Text, Visible, Avatar } from 'components';
import { Container, Row, Col, StyleSystemThemedProps } from 'components/layout';
import {
  Add,
  At,
  ChatFill,
  ClockFill,
  CloseThick,
  Ellipse,
  ExclamationMark,
  Pencil,
  Reply,
  Settings,
  Smiling,
} from 'icons';
import { metrics } from 'config';
import {
  MultipleNotificationsDocument,
  Notification,
  NotificationFragment,
  NotificationTypeEnum,
  User,
  useReadNotificationMutation,
} from 'expo-schema';
import { useResponsiveLayout } from 'hooks/responsive-layout';

import { getMessageDateTime } from 'utils/dateTime';

const { STYLES } = metrics;

export const Item: React.FC<NotificationItemProps> = ({
  notification,
  type,
  isAlertNotification,
  ...props
}) => {
  const { isMobile } = useResponsiveLayout();

  const [readNotification] = useReadNotificationMutation({
    update: (cache, { data }) => {
      const notificationId = data?.readNotification.notification?.id;

      const notifications = cache.readQuery({
        query: MultipleNotificationsDocument,
        variables: {
          limit: metrics.LIMITS.notifications,
          offset: 0,
        },
      }) as any;

      const MultipleNotifications = (
        notifications?.MultipleNotifications as NotificationFragment[]
      ).map((notificationItem) => {
        return notificationItem.id === notificationId
          ? { ...notificationItem, readAt: new Date() }
          : notificationItem;
      });

      cache.writeQuery({
        query: MultipleNotificationsDocument,
        data: { MultipleNotifications },
        variables: {
          limit: metrics.LIMITS.notifications,
          offset: 0,
        },
      });
    },
  });
  const iconBasis = 45;
  const messageBasis = isMobile ? '85%' : STYLES.happeningBarWidth - (45 + 20);
  const my = isAlertNotification ? '3xs' : 'xs';
  const from: User = notification?.notificationFromUser?.user as User;

  const icons: Record<NotificationTypeEnum, JSX.Element> = {
    CHAT_MESSAGE: <ChatFill width={8} height={8} colorVariant="title" />,
    CHAT_REACTION: <Smiling width={8} height={8} colorVariant="title" />,
    CHAT_REPLY: <Reply width={8} height={8} colorVariant="title" />,
    POST_MESSAGE: <ChatFill width={8} height={8} colorVariant="title" />,
    POST_REACTION: <Smiling width={8} height={8} colorVariant="title" />,
    POST_REPLY: <Reply width={8} height={8} colorVariant="title" />,
    MESSAGE_MENTION: <At width={8} height={8} colorVariant="title" />,
    BLOCK_MENTION: <At width={8} height={8} colorVariant="title" />,
    NEW_BLOCK: <Add width={8} height={8} colorVariant="title" />,
    BLOCK_MESSAGE_MENTION: <At width={8} height={8} colorVariant="title" />,
    ADDED_TO_ROOM: <Add width={8} height={8} colorVariant="title" />,
    ADDED_TO_SPACE: <Add width={8} height={8} colorVariant="title" />,
    REMINDER_EVENT: <ClockFill width={8} height={8} colorVariant="title" />,
    REMINDER_DUE_DATE: <ClockFill width={8} height={8} colorVariant="title" />,
    BLOCK_EDITED: <Pencil width={8} height={8} colorVariant="title" />,
    SUBSCRIPTION_RENEWAL_FAILURE: <CloseThick width={8} height={8} colorVariant="title" />,
    SUBSCRIPTION_RENEWAL_SOON: <ExclamationMark width={8} height={8} colorVariant="title" />,
    SYSTEM: <Settings width={8} height={8} colorVariant="title" />,
  };

  const getIcon = useCallback(() => {
    const notificationType = type || notification?.type;
    if (notificationType) {
      return (
        <Avatar
          size={18}
          borderedColor="base-01"
          bordered
          shapeVariant="circle"
          colorVariant="base-02"
          icon={icons[notificationType]}
        />
      );
    }
    return null;
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [notification?.type, type]);

  const openNotification = useCallback(
    (notificationItem: NotificationFragment) => {
      if (!notificationItem.readAt) {
        readNotification({
          variables: {
            id: notificationItem.id,
          },
          optimisticResponse: {
            readNotification: {
              __typename: 'ReadNotificationPayload',
              notification: {
                __typename: 'Notification',
                ...notificationItem,
                readAt: new Date(),
              } as NotificationFragment,
            },
          },
        });
      }
    },
    [readNotification]
  );
  return (
    <TouchableTile
      onPress={() => openNotification(notification as NotificationFragment)}
      variant="text"
      shapeVariant="square"
      underlayColorVariant="base"
      leftElement={
        <Card variant="plain" shapeVariant="square" colorVariant="transparent" {...props} my={my}>
          <Container style={{ flexDirection: 'row', alignItems: 'center' }}>
            <Row flexGrow={1} justifyContent="flex-start" alignItems="flex-start">
              <Visible if={!notification?.readAt}>
                <Container zIndex={1} position="absolute" left={-10}>
                  <Ellipse />
                </Container>
              </Visible>
              <Container flexBasis={iconBasis}>
                <Avatar
                  size={30}
                  shapeVariant="square"
                  colorVariant="base"
                  title={from.name.first}
                  uri={from.profilePhotoUrl as string}
                />
                <Container position="absolute" bottom={-5} right={5}>
                  {getIcon()}
                </Container>
              </Container>
              <Col flexBasis={messageBasis}>
                <Text variant="caption">
                  <Text variant="caption" weightVariant="bold" color="title">
                    {from.name.first}
                    {''} {from.name.last}
                  </Text>{' '}
                  <Text variant="caption" color="caption">
                    {notification?.bodyContentPreview}
                  </Text>
                </Text>
                <Text mt="3xs" variant="label" color="caption-01">
                  {getMessageDateTime(notification?.createdAt)}
                </Text>
              </Col>
            </Row>
          </Container>
        </Card>
      }
    />
  );
};

type NotificationItemProps = StyleSystemThemedProps & ItemProps;
export type RoomVariants = 'compact' | 'full';
export interface ItemProps {
  isAlertNotification?: boolean;
  type?: NotificationTypeEnum;
  notification?: Notification;
}
