import { type FC, useCallback, useEffect, useState } from 'react';
import { useMutation, useQuery } from 'react-query';
import { useNavigate, useParams } from 'react-router';
import { useSearchParams } from 'react-router-dom';

import { StreamVideo } from '@stream-io/video-react-sdk';
import { useModal } from '@material-hu/hooks/useModal';
import Container from '@material-hu/mui/Container';
import Stack from '@material-hu/mui/Stack';

import HuDialog from '@material-hu/components/design-system/Dialog';
import useHuSnackbar from '@material-hu/components/design-system/Snackbar';

import { logEvent } from 'src/config/amplitude';
import { ORGANIZER_LIMIT } from 'src/constants/events';
import { useAuth } from 'src/contexts/JWTContext';
import useHuGoTheme from 'src/hooks/useHuGoTheme';
import usePostReactions from 'src/hooks/usePostReactions';
import { useScrollableSX } from 'src/hooks/useSxScrollable';
import {
  deleteEvent,
  getEvent,
  getEventOrganizers,
  getEventPosts,
} from 'src/services/events';
import { EventName } from 'src/types/amplitude';
import { EventOrganizerStatus, EventTabs, EventType } from 'src/types/events';
import { StreamStatus, UserTypeStream } from 'src/types/stream';
import { useLokaliseTranslation } from 'src/utils/i18n';
import { addReaction, removeReaction } from 'src/utils/reactions';

import PostPlayerStreaming from '../../feed/components/PostPlayerStreaming';
import useGetStreamVideoClient from '../../liveStream/hooks/useGetStreamVideoClient';
import AttendeeCard from '../components/AttendeesCard';
import EventActions from '../components/EventActions';
import EventBackButton from '../components/EventBackButton';
import EventDetails from '../components/EventDetails';
import { EventFeed } from '../components/EventFeed';
import EventHeader from '../components/EventHeader';
import { OrganizerCard } from '../components/OrganizerCard';
import OrganizerInvitationBanner from '../components/OrganizerInvitationBanner';
import InfoCardSkeleton from '../components/skeleton/InfoCardSkeleton';
import { eventsKeys, updateLivestreamPostReactions } from '../queries';
import { eventsRoutes } from '../routes';

export const Event: FC = () => {
  const [searchParams] = useSearchParams();
  const { t } = useLokaliseTranslation('events');
  const { user } = useAuth();
  const { enqueueSnackbar } = useHuSnackbar();
  const client = useGetStreamVideoClient(UserTypeStream.VIEWER);
  const navigate = useNavigate();
  const id = Number(useParams().id);

  const ThemeProvider = useHuGoTheme();
  const scrollableSX = useScrollableSX('lg');
  const [isScrolled, setIsScrolled] = useState(false);
  const handleScroll = useCallback((e: React.UIEvent<HTMLDivElement>) => {
    setIsScrolled(e.currentTarget.scrollTop >= 10);
  }, []);
  const source = searchParams.get('source');

  const { data: event, isLoading } = useQuery(
    eventsKeys.event(id),
    () => getEvent(id),
    {
      select: r => r.data,
    },
  );

  const { data: showOrganizerInvitationBanner } = useQuery(
    eventsKeys.eventOrganizerBanner(id),
    () =>
      getEventOrganizers({
        id,
        limit: ORGANIZER_LIMIT.OWN_USER,
        userIds: [user!.id],
        excludeUserIds: [event!.user.id],
      }),
    {
      enabled: !!user?.id && !!event?.user.id,
      select: res => res.data.items[0].status === EventOrganizerStatus.PENDING,
    },
  );

  const { data: livestreamPost, isLoading: isLivestreamPostLoading } = useQuery(
    eventsKeys.eventPostsWithLivestream(id),
    () => getEventPosts(id, '', true),
    {
      select: res =>
        res.data.items.find(item => item.stream?.status === StreamStatus.LIVE),
      enabled: !!event?.liveStream,
    },
  );

  const isLive = livestreamPost?.stream?.status === StreamStatus.LIVE;
  const hasScrollEffect = isScrolled && (!!event?.coverPictureUrl || isLive);

  const { mutate } = useMutation(() => deleteEvent(id), {
    onSuccess: () => {
      enqueueSnackbar({
        title: t('DELETE_EVENT_SUCCESS'),
        variant: 'info',
      });
      navigate(eventsRoutes.events());
    },
    onError: () => {
      enqueueSnackbar({
        title: t('DELETE_EVENT_ERROR'),
        variant: 'error',
      });
    },
  });

  const {
    modal: deleteModal,
    showModal: showDeleteModal,
    closeModal: closeDeleteModal,
  } = useModal(
    () => (
      <HuDialog
        onClose={closeDeleteModal}
        title={t('DELETE_EVENT_TITLE')}
        textBody={t('DELETE_EVENT_DESCRIPTION', { event: event?.name })}
        primaryButtonProps={{
          children: t('ELIMINATE'),
          onClick: () => {
            mutate();
            closeDeleteModal();
          },
        }}
        secondaryButtonProps={{
          children: t('CANCEL'),
          onClick: closeDeleteModal,
        }}
      />
    ),
    {
      onClose: () => closeDeleteModal(),
    },
  );

  const { handleAddReaction, handleRemoveReaction, getReactionUsers } =
    usePostReactions({
      context: 'events',
      postId: livestreamPost?.id ?? 0,
      eventId: id,
      reactions: livestreamPost?.reactions ?? [],
      onAddReactionSuccess: (postId, emoji, unified) =>
        updateLivestreamPostReactions(id, postId, r =>
          addReaction(r, emoji, unified, true),
        ),
      onRemoveReactionSuccess: (postId, emoji) =>
        updateLivestreamPostReactions(id, postId, r =>
          removeReaction(r, emoji, true),
        ),
    });

  useEffect(() => {
    logEvent(EventName.EVENT_DETAIL_VIEWED, {
      eventId: event?.id,
      eventType:
        event?.videoCallUrl && event?.location
          ? EventType.IN_PERSON_AND_ONLINE
          : EventType.IN_PERSON,
      source: source ?? EventTabs.DIRECT_LINK,
    });
  }, []);

  return (
    <StreamVideo client={client}>
      <ThemeProvider>
        {deleteModal}
        <Container
          maxWidth="lg"
          sx={{ height: '100%', px: 3, pt: 3 }}
        >
          <Stack sx={{ height: '100%' }}>
            {(isLoading || isLivestreamPostLoading) && <InfoCardSkeleton />}
            {!isLoading && !isLivestreamPostLoading && event && (
              <>
                <EventBackButton source={source} />
                <Stack
                  onScroll={handleScroll}
                  sx={{
                    gap: 2,
                    pt: 2,
                    pb: 3,
                    maxHeight: '100%',
                    overflowY: 'auto',
                    ...scrollableSX,
                  }}
                >
                  <Stack
                    sx={{
                      flexDirection: 'row',
                      gap: 2,
                      alignItems: 'center',
                      justifyContent: 'space-between',
                    }}
                  >
                    <EventHeader
                      event={event}
                      hideDescription={hasScrollEffect}
                    />
                    <EventActions
                      event={event}
                      user={user}
                      showDeleteModal={showDeleteModal}
                      isLivestreamActive={
                        livestreamPost?.stream?.status === StreamStatus.LIVE
                      }
                      sx={{
                        flexShrink: 0,
                        justifyContent: 'flex-end',
                      }}
                    />
                  </Stack>
                  <Stack
                    sx={{
                      flexDirection: 'row',
                      gap: 2,
                      alignItems: 'flex-start',
                    }}
                  >
                    <Stack
                      sx={{
                        flex: 2,
                        gap: 2,
                        flexShrink: 0, // stop the column from growing if content is too wide
                        overflow: 'hidden',
                      }}
                    >
                      {showOrganizerInvitationBanner && (
                        <OrganizerInvitationBanner event={event} />
                      )}

                      {event.coverPictureUrl && !livestreamPost && (
                        <Stack
                          component="img"
                          src={event.coverPictureUrl}
                          sx={{ borderRadius: 1 }}
                        />
                      )}
                      {livestreamPost?.stream?.status === StreamStatus.LIVE && (
                        <PostPlayerStreaming
                          stream={livestreamPost.stream}
                          post={{
                            user: livestreamPost.user,
                            updatedAt: livestreamPost.updatedAt,
                            createdAt: livestreamPost.createdAt,
                            reactions: livestreamPost.reactions,
                            id: livestreamPost.id,
                            commentCount: livestreamPost.commentCount,
                            commentsEnabled: livestreamPost.commentsEnabled,
                            body: livestreamPost.body,
                            bodyAttributes: livestreamPost.bodyAttributes,
                            bodyHtml: livestreamPost.bodyHtml,
                            event: { id: event.id, title: event.name },
                          }}
                          reactionsHandlers={{
                            handleAddReaction,
                            handleRemoveReaction,
                            getReactionUsers,
                          }}
                        />
                      )}
                      <EventDetails
                        event={event}
                        user={user}
                      />
                      <EventFeed
                        event={event}
                        isLivestreamActive={
                          livestreamPost?.stream?.status === StreamStatus.LIVE
                        }
                      />
                    </Stack>
                    <Stack sx={{ flex: 1, gap: 2 }}>
                      <OrganizerCard event={event} />
                      <AttendeeCard event={event} />
                    </Stack>
                  </Stack>
                </Stack>
              </>
            )}
          </Stack>
        </Container>
      </ThemeProvider>
    </StreamVideo>
  );
};

export default Event;
