import { FC, Fragment, useEffect, useState } from 'react';
import { useFormContext } from 'react-hook-form';
import { useInfiniteQuery, useQuery } from 'react-query';
import { useSearchParams } from 'react-router-dom';

import { useDebounce } from '@material-hu/hooks/useDebounce';
import { IconAlertTriangle, IconSearch } from '@material-hu/icons/tabler';
import Divider from '@material-hu/mui/Divider';
import Stack from '@material-hu/mui/Stack';
import { useTheme } from '@material-hu/mui/styles';

import HuCardContainer from '@material-hu/components/design-system/CardContainer';
import HuSearch from '@material-hu/components/design-system/Inputs/Search';
import HuList from '@material-hu/components/design-system/List';
import HuListItem from '@material-hu/components/design-system/List/components/ListItem';
import HuRadioButton from '@material-hu/components/design-system/RadioButton/RadioButton';
import HuTitle from '@material-hu/components/design-system/Title';

import useGeneralError from 'src/hooks/useGeneralError';
import { getDraftFeed, getDraftGroups } from 'src/services/posts';
import { DraftGroup } from 'src/types/posts';
import { useLokaliseTranslation } from 'src/utils/i18n';
import { flatPages } from 'src/utils/pagination';

import { InfiniteList } from 'src/components/list';

import { NewPostDraftSteps } from '../../constants';
import { postDraftKeys } from '../../queries';
import EmptyState from '../EmptyState';
import ListSkeleton from '../skeleton/ListSkeleton';

const LIMIT = 5;

const Target: FC = () => {
  const [query, setQuery] = useState<string>('');

  const { t } = useLokaliseTranslation(['communication', 'post', 'group']);
  const theme = useTheme();
  const showGeneralError = useGeneralError();
  const { setValue, watch, getValues } = useFormContext();
  const debouncedQuery = useDebounce(query);
  const [searchParams, setSearchParams] = useSearchParams();
  const groupId = searchParams.get('groupId');

  const { permissionId, authorFullName, groupId: formGroupId } = getValues();

  useEffect(() => {
    if (formGroupId !== null && groupId === null) {
      setValue('groupId', null);
    }
  }, []);

  const {
    data: draftGroupsInfinite,
    isLoading: isLoadingGroups,
    fetchNextPage,
    hasNextPage,
    isFetchingNextPage,
  } = useInfiniteQuery(
    postDraftKeys.groups(permissionId, debouncedQuery),
    ({ pageParam = '' }) =>
      getDraftGroups(permissionId, {
        limit: LIMIT,
        cursor: pageParam,
        q: debouncedQuery || null,
      }),
    {
      getNextPageParam: lastPage => lastPage?.data?.cursor,
      onError: err => {
        showGeneralError(
          err,
          t('drafts_for_review.error_loading_draft_groups'),
        );
      },
    },
  );

  const draftGroups = flatPages(draftGroupsInfinite);

  const { data: feedData, isLoading: isLoadingFeed } = useQuery(
    postDraftKeys.feed(permissionId),
    () => getDraftFeed(permissionId),
    {
      select: res => res?.data,
    },
  );

  const handleChangeQuery = (value: string) => setQuery(value);

  const showFeedCard = feedData?.canPostInFeed;

  const showGroupCard = debouncedQuery !== '' || draftGroups?.length > 0;

  const noResults =
    !isLoadingGroups && !!debouncedQuery && !draftGroups?.length;

  const isEmpty =
    !isLoadingGroups &&
    !isLoadingFeed &&
    !draftGroups?.length &&
    !feedData?.canPostInFeed &&
    !debouncedQuery;
  const handleChangeGroup = (group: DraftGroup) => {
    setValue('groupId', group.id);
    setValue('groupTitle', group.title);
    setValue('toFeed', false);
    setSearchParams({
      ...Object.fromEntries(searchParams.entries()),
      groupId: group.id.toString(),
      canSendPostNotification: group.loggedUserIsAdmin.toString(),
      canCreatePoll: 'true',
    });
  };

  const handleChangeFeed = () => {
    setValue('groupId', null);
    setValue('groupTitle', null);
    setValue('toFeed', true);
    searchParams.delete('groupId');
    setSearchParams({
      ...Object.fromEntries(searchParams.entries()),
      canSendPostNotification: String(
        feedData?.canSendPostNotification ?? false,
      ),
      canCreatePoll: String(feedData?.canCreatePoll ?? false),
    });
  };

  const isLoadingInitial = isLoadingFeed && isLoadingGroups;

  return (
    <Stack sx={{ gap: 3 }}>
      <HuTitle
        title={t('communication:drafts_for_review.title', {
          context: NewPostDraftSteps.TARGET,
        })}
        variant="S"
        sx={{ gap: 2 }}
      />
      {isLoadingInitial && (
        <HuCardContainer fullWidth>
          <ListSkeleton />
        </HuCardContainer>
      )}
      {!isLoadingInitial && !isEmpty && (
        <>
          {showFeedCard && (
            <HuCardContainer fullWidth>
              <HuRadioButton
                onClick={() => handleChangeFeed()}
                label={t('communication:drafts_for_review.post_in_feed', {
                  moduleName: t('post:feed'),
                })}
                isActive={watch('toFeed') === true}
                stackSx={{ gap: 2 }}
              />
            </HuCardContainer>
          )}
          {showGroupCard && (
            <HuCardContainer fullWidth>
              <HuTitle
                title={t('drafts:steps.destiny.groups_in_common', {
                  author: authorFullName,
                })}
                variant="S"
              />
              <HuSearch
                value={query}
                onChange={handleChangeQuery}
                fullWidth
                sx={{ mt: 2, mb: 3 }}
              />
              {noResults && (
                <EmptyState
                  avatarProps={{
                    Icon: IconSearch,
                  }}
                  titleProps={{
                    title: '',
                    description: t(
                      'communication:drafts_for_review.no_results_description',
                    ),
                  }}
                />
              )}
              <HuList>
                <InfiniteList
                  isSuccess={!!draftGroups}
                  isLoading={isLoadingGroups}
                  fetchNextPage={fetchNextPage}
                  hasNextPage={hasNextPage}
                  isFetchingNextPage={isFetchingNextPage}
                  customLoader={
                    <Stack sx={{ ml: 2 }}>
                      <HuListItem loading />
                      <HuListItem loading />
                    </Stack>
                  }
                  renderSkeleton={
                    <Stack sx={{ ml: 2 }}>
                      <HuListItem loading />
                      <HuListItem loading />
                      <HuListItem loading />
                    </Stack>
                  }
                >
                  {draftGroups?.map((group, index) => (
                    <Fragment key={group?.id}>
                      <HuRadioButton
                        label={group.title}
                        description={`${t(`group:groups_group_title_${group?.privacyPolicy.toLowerCase()}`)} • ${t('group:member', { count: group.membersCount })}`}
                        onClick={() => handleChangeGroup(group)}
                        isActive={watch('groupId') === group?.id}
                        avatarProps={{ src: group.icon }}
                      />
                      {index !== draftGroups.length - 1 && (
                        <Divider sx={{ my: 1.5 }} />
                      )}
                    </Fragment>
                  ))}
                </InfiniteList>
              </HuList>
            </HuCardContainer>
          )}
        </>
      )}
      {isEmpty && (
        <EmptyState
          avatarProps={{
            Icon: IconAlertTriangle,
            color: 'warning',
          }}
          titleProps={{
            title: t('drafts:steps.destiny.empty'),
            description: t(
              'communication:drafts_for_review.no_target_description',
            ),
          }}
          sx={{
            borderRadius: theme.shape.borderRadiusL,
            border: `1px solid ${theme.palette.new.border.neutral.default}`,
          }}
        />
      )}
    </Stack>
  );
};

export default Target;
