import { useEffect, useMemo, useRef, useState } from 'react';
import { Helmet } from 'react-helmet-async';
import { FormProvider } from 'react-hook-form';
import { useInfiniteQuery, useQuery } from 'react-query';
import { useNavigate } from 'react-router';

import { useQueryState } from 'nuqs';
import { useDebounce } from '@material-hu/hooks/useDebounce';
import useHuPagination from '@material-hu/hooks/useHuPagination';
import {
  IconClipboardCheck,
  IconInfoTriangle,
  IconSpy,
  IconSpyOff,
} from '@material-hu/icons/tabler';
import Stack from '@material-hu/mui/Stack/Stack';

import Avatar from '@material-hu/components/design-system/Avatar';
import CardContainer from '@material-hu/components/design-system/CardContainer';
import StateCard from '@material-hu/components/design-system/StateCard';
import Tabs from '@material-hu/components/design-system/Tabs';
import { Title } from '@material-hu/components/design-system/Title';

import { useAuth } from 'src/contexts/JWTContext';
import useHuGoTheme from 'src/hooks/useHuGoTheme';
import { useScrollRestoration } from 'src/hooks/useScrollRestoration';
import { getAvailableSurveys, getCompletedSurveys } from 'src/services/surveys';
import { type FormAttributes, type FormItemResponse } from 'src/types/forms';
import { formatRelativeDate } from 'src/utils/date';
import { formatTitle } from 'src/utils/helmetUtils';
import { useLokaliseTranslation } from 'src/utils/i18n';
import {
  flatPages,
  getListItemsLength,
  getNextPage,
} from 'src/utils/pagination';

import SurveyList from './components/SurveyList';
import { surveysKeys } from './queries';
import { surveysRoutes } from './routes';

const SCROLL_CONTAINER_ID = 'survey-catalog-scroll-container';
const SCROLL_STORAGE_KEY = 'survey-catalog-scroll-position';

export type SurveyCatalogTabs = 'available' | 'completed';

const SurveyCatalog = () => {
  const { t } = useLokaliseTranslation(['surveys', 'forms']);
  const HugoThemeProvider = useHuGoTheme();
  const navigate = useNavigate();
  const { user } = useAuth();

  const savedScrollPosition = useRef(
    Number(sessionStorage.getItem(SCROLL_STORAGE_KEY)) || 0,
  ).current;
  const [isScrollRestorationDisabled, setIsScrollRestorationDisabled] =
    useState(false);

  useEffect(() => {
    let timeoutId: NodeJS.Timeout;

    const handleScroll = () => {
      setIsScrollRestorationDisabled(true);

      clearTimeout(timeoutId);
      timeoutId = setTimeout(() => {
        const element = document.getElementById(SCROLL_CONTAINER_ID);
        if (element) {
          sessionStorage.setItem(SCROLL_STORAGE_KEY, String(element.scrollTop));
        }
      }, 300);
    };

    const element = document.getElementById(SCROLL_CONTAINER_ID);
    element?.addEventListener('scroll', handleScroll, { passive: true });

    return () => {
      element?.removeEventListener('scroll', handleScroll);
      clearTimeout(timeoutId);
    };
  }, []);

  useScrollRestoration({
    scrollPosition: savedScrollPosition,
    containerId: SCROLL_CONTAINER_ID,
    disabled: isScrollRestorationDisabled,
  });

  const { Search, params, form } = useHuPagination({
    defaultPage: 1,
    defaultLimit: 10,
    defaultSearch: '',
  });

  const [tab, setTab] = useQueryState('tab', {
    defaultValue: 'available',
  });

  const debouncedSearch = useDebounce(params.search);

  const { pagination, search: _search, ...restParams } = params;
  const limit = pagination.limit;

  const parsedParams = useMemo(
    () => ({
      ...restParams,
      limit,
      title: debouncedSearch,
    }),
    [limit, debouncedSearch],
  );

  const {
    data: availableSurveysData,
    isLoading: isLoadingAvailableSurveys,
    isFetchingNextPage: isFetchingNextPageAvailableSurveys,
    fetchNextPage: fetchNextPageAvailableSurveys,
    hasNextPage: hasNextPageAvailableSurveys,
    isError: isErrorAvailableSurveys,
    refetch: refetchAvailableSurveys,
  } = useInfiniteQuery(
    surveysKeys.surveys.list({ ...parsedParams, type: 'available' }),
    ({ pageParam = 1 }) =>
      getAvailableSurveys({ ...parsedParams, page: pageParam }),
    {
      getNextPageParam: (_, pages) =>
        getNextPage(getListItemsLength(pages), parsedParams.limit, pages),
    },
  );

  const { data: availableSurveysTotalData } = useQuery(
    surveysKeys.surveys.list({ limit: 1, type: 'available' }),
    () => getAvailableSurveys({ page: 1, limit: 1 }),
  );

  const availableSurveysTotal = availableSurveysTotalData?.data?.count ?? 0;

  const {
    data: completedSurveysData,
    isLoading: isLoadingCompletedSurveys,
    isFetchingNextPage: isFetchingNextPageCompletedSurveys,
    fetchNextPage: fetchNextPageCompletedSurveys,
    hasNextPage: hasNextPageCompletedSurveys,
    isError: isErrorCompletedSurveys,
    refetch: refetchCompletedSurveys,
  } = useInfiniteQuery(
    surveysKeys.surveys.list({ ...parsedParams, type: 'completed' }),
    ({ pageParam = 1 }) =>
      getCompletedSurveys(user?.id ?? 0, { ...parsedParams, page: pageParam }),
    {
      getNextPageParam: (_, pages) =>
        getNextPage(getListItemsLength(pages), parsedParams.limit, pages),
    },
  );

  const handleRefetchOnError = () => {
    if (tab === 'available') {
      refetchAvailableSurveys();
    } else {
      refetchCompletedSurveys();
    }
  };

  const availableSurveys = flatPages(availableSurveysData);
  const completedSurveys = flatPages(completedSurveysData);

  const handleNavigateToAvailableSurvey = (survey: FormAttributes) => {
    navigate(surveysRoutes.survey.form(survey.id));
  };

  const handleNavigateToCompletedSurvey = (survey: FormItemResponse) => {
    navigate(
      surveysRoutes.survey.completedDetail(survey.templateId, survey.formId),
    );
  };

  const isError = isErrorAvailableSurveys || isErrorCompletedSurveys;
  const isAvailableTab = tab === 'available';
  const isCompletedTab = tab === 'completed';
  const hasSearch = Boolean(debouncedSearch);

  const isAvailableEmpty =
    isAvailableTab &&
    !isError &&
    !isLoadingAvailableSurveys &&
    availableSurveys.length === 0;
  const isCompletedEmpty =
    isCompletedTab &&
    !isError &&
    !isLoadingCompletedSurveys &&
    completedSurveys.length === 0;

  return (
    <HugoThemeProvider>
      <Helmet>
        <title>{formatTitle(t('surveys'))}</title>
      </Helmet>
      <Stack
        id={SCROLL_CONTAINER_ID}
        sx={{
          height: 1,
          overflow: 'auto',
          backgroundColor: theme => theme.palette.new.background.layout.default,
        }}
      >
        <FormProvider {...form}>
          <Stack
            sx={{
              py: 4,
              width: 1,
              maxWidth: 'xl',
              mx: 'auto',
              px: 3,
              gap: 3,
            }}
          >
            <Title
              variant="XL"
              title={t('surveys')}
            />
            <Tabs
              value={tab}
              onTabChange={value => setTab(value)}
              tabs={[
                {
                  label: t('forms:available_surveys'),
                  value: 'available',
                  hasBadge: availableSurveysTotal > 0,
                },
                {
                  label: t('forms:completed_surveys'),
                  value: 'completed',
                },
              ]}
            />
            <Search inputProps={{ placeholder: t('search_survey') }} />
            {isError && (
              <StateCard
                variant="error"
                icon={IconInfoTriangle}
                title={t('survey_list_empty.error_title')}
                description={t('survey_list_empty.error_description')}
                primaryAction={{
                  label: t('general:try_again'),
                  onClick: handleRefetchOnError,
                }}
              />
            )}
            {isAvailableEmpty && (
              <StateCard
                title={t(
                  hasSearch
                    ? 'survey_list_empty.search_title'
                    : 'survey_list_empty.available_title',
                )}
                description={t(
                  hasSearch
                    ? 'survey_list_empty.search_description'
                    : 'survey_list_empty.available_description',
                )}
              />
            )}
            {isAvailableTab && (
              <SurveyList
                items={availableSurveys}
                isLoading={isLoadingAvailableSurveys}
                isFetchingNextPage={isFetchingNextPageAvailableSurveys}
                hasNextPage={hasNextPageAvailableSurveys}
                fetchNextPage={fetchNextPageAvailableSurveys}
                keyExtractor={survey => survey.id}
                renderItem={survey => (
                  <CardContainer
                    fullWidth
                    sx={{
                      backgroundColor: theme =>
                        theme.palette.new.background.layout.tertiary,
                    }}
                    onClick={() => handleNavigateToAvailableSurvey(survey)}
                  >
                    <Stack
                      sx={{
                        flexDirection: 'row',
                        alignItems: 'center',
                        gap: 1,
                      }}
                    >
                      <Avatar
                        color="primary"
                        Icon={survey.isAnonymous ? IconSpy : IconClipboardCheck}
                      />
                      <Title
                        variant="S"
                        title={survey.title}
                        description={
                          survey.isAnonymous
                            ? t('survey_list_row.anonymous_description')
                            : undefined
                        }
                      />
                    </Stack>
                  </CardContainer>
                )}
              />
            )}
            {isCompletedEmpty && (
              <StateCard
                title={t(
                  hasSearch
                    ? 'survey_list_empty.search_title'
                    : 'survey_list_empty.answered_title',
                )}
                description={t(
                  hasSearch
                    ? 'survey_list_empty.search_description'
                    : 'survey_list_empty.answered_description',
                )}
              />
            )}
            {isCompletedTab && (
              <SurveyList
                items={completedSurveys}
                isLoading={isLoadingCompletedSurveys}
                isFetchingNextPage={isFetchingNextPageCompletedSurveys}
                hasNextPage={hasNextPageCompletedSurveys}
                fetchNextPage={fetchNextPageCompletedSurveys}
                keyExtractor={survey => survey.formId}
                renderItem={survey => {
                  const isAnonymous =
                    survey.formChat?.form?.isAnonymous ?? false;
                  const lastMessage = survey.lastMessage?.createdAt;
                  return (
                    <CardContainer
                      fullWidth
                      sx={{
                        backgroundColor: theme =>
                          theme.palette.new.background.layout.tertiary,
                      }}
                      onClick={() => handleNavigateToCompletedSurvey(survey)}
                    >
                      <Stack
                        sx={{
                          flexDirection: 'row',
                          alignItems: 'center',
                          gap: 1,
                        }}
                      >
                        <Avatar
                          color="primary"
                          Icon={isAnonymous ? IconSpyOff : IconClipboardCheck}
                        />
                        <Title
                          variant="S"
                          title={survey.title}
                          description={`#${survey.formId}`}
                          copetin={formatRelativeDate(new Date(lastMessage))}
                        />
                      </Stack>
                    </CardContainer>
                  );
                }}
              />
            )}
          </Stack>
        </FormProvider>
      </Stack>
    </HugoThemeProvider>
  );
};

export default SurveyCatalog;
