import { FC, useState } from 'react';
import { Helmet } from 'react-helmet-async';

import { useMutation, useQuery } from 'react-query';
import { useNavigate } from 'react-router-dom';
import { Navigate } from 'react-router-dom';

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

import useGeneralError from 'src/hooks/useGeneralError';
import useRequiredParams from 'src/hooks/useRequiredParams';
import {
  getGroupDetails,
  getGroupPostDetails,
  getGroupPostInsightsAudience,
  getGroupPostInsightsAudienceReport,
  getGroupPostInsightsSummary,
  getGroupPostInsightsSummaryReport,
  getGroupLiveStreamStats,
  getGroupLiveStreamTimeline,
  getGroupLiveStreamViewerReports,
  getGroupLiveStreamReport,
} from 'src/services/groups';
import { AudienceTypes } from 'src/types/stream';
import { getDownloadReportName } from 'src/utils/feed';
import { downloadBlob } from 'src/utils/files';
import { getUserGroupRoles } from 'src/utils/groups';
import { formatTitle } from 'src/utils/helmetUtils';
import { useLokaliseTranslation as useTranslation } from 'src/utils/i18n';

import { getDownloadLiveReportName } from 'src/components/post/insights/livestream/utils';
import PostInsights from 'src/components/post/insights/PostInsights';

import useCanViewGroupsInsights from './hooks/useCanViewGroupsInsights';
import { groupsKeys } from './queries';
import { groupsRoutes } from './routes';

const GroupPostInsights: FC = () => {
  const { id, postId } = useRequiredParams(['id', 'postId'], -1);
  const [isDownloadingSummary, setIsDownloadingSummary] =
    useState<boolean>(false);
  const [isDownloadingAudience, setIsDownloadingAudience] =
    useState<boolean>(false);

  const { t } = useTranslation('post');
  const navigate = useNavigate();
  const showGeneralError = useGeneralError();
  const { enqueueSnackbar } = useHuSnackbar();

  const { data } = useQuery(groupsKeys.detail(id), () => getGroupDetails(id), {
    select: res => res?.data,
    onError: err => {
      showGeneralError(err, t('error_loading_group'));
    },
  });

  const postDataQuery = useQuery(
    groupsKeys.postDetail(id, postId),
    () => getGroupPostDetails(id, postId),
    {
      onError: err => {
        showGeneralError(err, t('error_loading_post'));
      },
    },
  );

  const { isGroupAdmin } = getUserGroupRoles(data?.members ?? []);
  const user = postDataQuery?.data?.data?.user;
  const canViewInsights = useCanViewGroupsInsights(isGroupAdmin, user?.id);

  const insightSummaryQuery = useQuery(
    groupsKeys.insights.summary(id, postId),
    () => getGroupPostInsightsSummary(Number(id), Number(postId)),
    {
      onError: err => {
        showGeneralError(err, t('error_loading_insights_summary'));
      },
      enabled: !!id,
    },
  );

  const {
    mutate: downloadLiveStreamReport,
    isLoading: isDownloadingLiveStreamReport,
  } = useMutation(
    async () => {
      const { data: reportData } = await getGroupLiveStreamReport(id, postId);
      downloadBlob(
        reportData,
        getDownloadLiveReportName(
          postDataQuery.data?.data?.createdAt.toString() ?? '',
          postId,
        ),
      );
    },
    {
      onError: () => {
        showGeneralError({
          title: t('post:live_stream_metrics_download_error'),
        });
      },
    },
  );

  const handleDownloadSummary = async () => {
    try {
      setIsDownloadingSummary(true);

      const { data: reportData } = await getGroupPostInsightsSummaryReport(
        Number(id),
        Number(postId),
      );
      downloadBlob(
        reportData,
        getDownloadReportName(t('summary').toLowerCase()),
      );

      enqueueSnackbar({
        title: t('success_download_summary'),
        variant: 'success',
      });
    } catch (err) {
      enqueueSnackbar({
        title: t('error_download_summary'),
        variant: 'error',
      });
    } finally {
      setIsDownloadingSummary(false);
    }
  };

  const handleDownloadAudience = async () => {
    try {
      setIsDownloadingAudience(true);

      const { data: reportData } = await getGroupPostInsightsAudienceReport(
        Number(id),
        Number(postId),
      );
      downloadBlob(
        reportData,
        getDownloadReportName(t('post:audience_web').toLowerCase()),
      );
      enqueueSnackbar({
        title: t('success_download_audience'),
        variant: 'success',
      });
    } catch (err) {
      enqueueSnackbar({
        title: t('error_download_audience'),
        variant: 'error',
      });
    } finally {
      setIsDownloadingAudience(false);
    }
  };

  if (user && !canViewInsights) {
    return <Navigate to={groupsRoutes.detail(id)} />;
  }

  return (
    <>
      <Helmet>
        <title>{formatTitle(t('insights'))}</title>
      </Helmet>
      <PostInsights
        onClose={() => navigate(groupsRoutes.detail(id))}
        onGoToPostDetail={groupsRoutes.post.detail(id, postId)}
        postDataQuery={postDataQuery}
        summaryProps={{
          insightSummaryQuery,
          downloadProps: {
            onDownloadSummary: handleDownloadSummary,
            isDownloadingSummary: isDownloadingSummary,
          },
        }}
        audienceProps={{
          serviceProps: {
            service: (...args) =>
              getGroupPostInsightsAudience(id, Number(postId), ...args),
            key: (...args) => groupsKeys.insights.audience(id, postId, ...args),
          },
          downloadProps: {
            onDownload: handleDownloadAudience,
            isDownloading: isDownloadingAudience,
          },
        }}
        liveStreamProps={{
          timeline: {
            service: () => getGroupLiveStreamTimeline(id, postId),
            keys: groupsKeys.insights.liveStreamTimeline(id, postId),
          },
          stats: {
            service: () => getGroupLiveStreamStats(id, postId),
            keys: groupsKeys.insights.liveStreamStats(id, postId),
          },
          viewerReports: {
            service: ({ q, limit, cursor, audienceType }) =>
              getGroupLiveStreamViewerReports({
                groupId: id,
                postId,
                q,
                limit,
                cursor,
                audienceType,
              }),
            keys: (type: AudienceTypes, query: string) =>
              groupsKeys.insights.liveStreamViewerReports(
                id,
                postId,
                type,
                query,
              ),
          },
          download: {
            onDownload: downloadLiveStreamReport,
            isDownloading: isDownloadingLiveStreamReport,
          },
        }}
      />
    </>
  );
};

export default GroupPostInsights;
