import React, { FC, useState } from 'react';
import { FormProvider } from 'react-hook-form';
import { useInfiniteQuery, useMutation, useQuery } from 'react-query';

import { useDebounce } from '@material-hu/hooks/useDebounce';
import { useDrawer } from '@material-hu/hooks/useDrawer';
import { useModal } from '@material-hu/hooks/useModal';
import {
  IconDownload,
  IconShieldMinus,
  IconShieldPlus,
  IconTrash,
} from '@material-hu/icons/tabler';
import Stack from '@material-hu/mui/Stack';
import Typography from '@material-hu/mui/Typography';

import MenuList from '@material-hu/components/composed-components/MenuList';
import HuAlert from '@material-hu/components/design-system/Alert';
import Button from '@material-hu/components/design-system/Buttons/Button';
import Dialog from '@material-hu/components/design-system/Dialog';
import Search from '@material-hu/components/design-system/Inputs/Search';
import useSnackbar from '@material-hu/components/design-system/Snackbar';
import Table from '@material-hu/components/design-system/Table';
import TableBody from '@material-hu/components/design-system/Table/components/TableBody';
import TableCell from '@material-hu/components/design-system/Table/components/TableCell';
import TableContainer from '@material-hu/components/design-system/Table/components/TableContainer';
import TableHead from '@material-hu/components/design-system/Table/components/TableHead';
import TableRow from '@material-hu/components/design-system/Table/components/TableRow';
import Title from '@material-hu/components/design-system/Title';

import { logEvent } from 'src/config/logging';
import { useAuth } from 'src/contexts/JWTContext';
import useFeatureFlag from 'src/hooks/useFeatureFlag';
import useHuGoTheme from 'src/hooks/useHuGoTheme';
import useRequiredParams from 'src/hooks/useRequiredParams';
import {
  getGroupDetails,
  getManageGroupMembers,
  removeMember,
  updateMemberRole,
} from 'src/services/groups';
import { EventName } from 'src/types/amplitude';
import { FeatureFlags } from 'src/types/featureFlags';
import { GroupMemberRoles } from 'src/types/groups';
import { formatUTCDate } from 'src/utils/date';
import { isSameInstance } from 'src/utils/groups';
import { useLokaliseTranslation as useTranslation } from 'src/utils/i18n';

import EllipsisTooltip from 'src/components/EllipsisTooltip';
import { InfiniteList } from 'src/components/list';
import { NoMoreResultsFooter } from 'src/components/NoMoreResultsFooter';
import { NoResultsLabel } from 'src/components/NoResultsLabel';
import { UserNameLink } from 'src/components/UserNameLink';

import { GROUP_MANAGEMENT_LAYOUT_CONTENT_ID } from '../../components/GroupManagementLayout';
import { groupsKeys } from '../../queries';
import { isSourceSegmentation } from '../../utils';
import GroupMembersReportDrawer from '../Reports/GroupMembersReportDrawer';
import useGroupMembersReportDownload from '../Reports/hooks/useGroupMembersReportDownload';

const { REGULAR, ADMIN } = GroupMemberRoles;

const ManageMembers: FC = () => {
  const { id: groupId } = useRequiredParams(['id']);
  const { data: groupDetails } = useQuery(
    groupsKeys.detail(groupId),
    () => getGroupDetails(groupId),
    {
      select: res => res?.data,
      enabled: !!groupId,
    },
  );
  const { t } = useTranslation(['group']);
  const { user, instance } = useAuth();
  const { enqueueSnackbar } = useSnackbar();
  const HuGoThemeProvider = useHuGoTheme();
  const [query, setQuery] = useState('');
  const debouncedQuery = useDebounce(query);
  const isDownloadGroupMembersReportEnabled = useFeatureFlag(
    FeatureFlags.DOWNLOAD_GROUP_MEMBERS_REPORT,
  );

  const {
    data,
    isLoading,
    refetch,
    fetchNextPage,
    hasNextPage,
    isFetchingNextPage,
    isSuccess,
  } = useInfiniteQuery(
    groupsKeys.searchManageMember(groupId, { q: debouncedQuery }),
    ({ pageParam = 1 }) =>
      getManageGroupMembers(groupId, {
        q: debouncedQuery ? debouncedQuery : undefined,
        page: pageParam,
        limit: 20,
      }),
    {
      enabled: !!groupId,
      getNextPageParam: lastPage =>
        lastPage?.data?.page < lastPage?.data?.totalPages
          ? lastPage?.data?.page + 1
          : undefined,
    },
  );

  const { mutate: removeUser } = useMutation(
    (userId: number) => removeMember(groupId, userId),
    {
      onSuccess: (resp, removedUserId) => {
        refetch();
        logEvent(EventName.GROUPS_USER_REMOVED, {
          userId: user!.id,
          groupId,
          removedUserId,
        });
        enqueueSnackbar({
          title: t('group:remove_member_success'),
          variant: 'success',
        });
      },
    },
  );

  const { mutate: updateUserRole } = useMutation(
    ({ userId, ...body }: { userId: number; role: GroupMemberRoles }) =>
      updateMemberRole(groupId, userId, body),
    {
      onSuccess: (resp, { userId: updatedUserId, role }) => {
        refetch();
        logEvent(EventName.GROUPS_USER_ROLE_CHANGED, {
          userId: user!.id,
          groupId,
          updatedUserId,
          newRole: role,
        });
        enqueueSnackbar({
          title: t('group:role_updated_success'),
          variant: 'success',
        });
      },
    },
  );

  const isAdmin = (role: GroupMemberRoles) => role === ADMIN;

  const members = data?.pages.flatMap(page => page.data.items) || [];

  const { submitGroupMembersReport, groupMembersReportDrawerForm } =
    useGroupMembersReportDownload(groupId);

  const {
    drawer: groupMembersReportDrawer,
    showDrawer: showGroupMembersReportDrawer,
    closeDrawer: closeGroupMembersReportDrawer,
  } = useDrawer(GroupMembersReportDrawer, {
    title: t('group:group_members_report_drawer_title_web'),
    primaryButtonProps: {
      children: t('group:send_report_web'),
      sx: { flex: 1 },
      onClick: async () => {
        await submitGroupMembersReport();
        closeGroupMembersReportDrawer();
      },
      disabled: !groupMembersReportDrawerForm.formState.isValid,
    },
    secondaryButtonProps: {
      children: t('general:cancel'),
      sx: { flex: 1 },
      onClick: () => closeGroupMembersReportDrawer(),
    },
  });

  const DeleteMemberModal: React.FC<{ userId: number }> = ({ userId }) => (
    <Dialog
      title={t('group:remove_member_modal_title_web')}
      textBody={t('group:remove_member_modal_body_web')}
      primaryButtonProps={{
        children: t('group:remove_member_modal_confirm_web'),
        onClick: () => {
          removeUser(userId);
          closeDeleteMemberModal();
        },
      }}
      secondaryButtonProps={{
        children: t('general:cancel'),
        onClick: closeDeleteMemberModal,
      }}
      onClose={closeDeleteMemberModal}
    />
  );

  const {
    modal: deleteMemberModal,
    showModal: showDeleteMemberModal,
    closeModal: closeDeleteMemberModal,
  } = useModal(DeleteMemberModal, { fullWidth: true });

  const UpdateRoleModal: React.FC<{
    userId: number;
    userRole: GroupMemberRoles;
    newRole: GroupMemberRoles;
  }> = ({
    userId,
    userRole,
    newRole,
  }: {
    userId: number;
    userRole: GroupMemberRoles;
    newRole: GroupMemberRoles;
  }) => (
    <Dialog
      title={t(`group:update_role_modal_title_${userRole.toLowerCase()}`)}
      textBody={t(`group:update_role_modal_body_${userRole.toLowerCase()}`)}
      primaryButtonProps={{
        children: t(
          `group:update_role_modal_confirm_${userRole.toLowerCase()}`,
        ),
        onClick: () => {
          updateUserRole({ userId, role: newRole });
          closeUpdateRoleModal();
        },
      }}
      secondaryButtonProps={{
        children: t('general:cancel'),
        onClick: closeUpdateRoleModal,
      }}
      onClose={closeUpdateRoleModal}
    />
  );

  const {
    modal: updateRoleModal,
    showModal: showUpdateRoleModal,
    closeModal: closeUpdateRoleModal,
  } = useModal(UpdateRoleModal, { fullWidth: true });

  const handleUpdateMemberRole = (userId: number, userRole: GroupMemberRoles) =>
    showUpdateRoleModal({
      userId,
      userRole,
      newRole: isAdmin(userRole) ? REGULAR : ADMIN,
    });

  const isEmpty = isSuccess && !members.length;

  const showNoMoreResultsFooter =
    !isEmpty && !hasNextPage && !isLoading && data && data.pages.length > 1;

  return (
    <Stack
      sx={{
        gap: 1,
        width: '100%',
        mb: 2,
        maxWidth: theme => theme.breakpoints.values.lg,
      }}
    >
      {deleteMemberModal}
      {updateRoleModal}
      <FormProvider {...groupMembersReportDrawerForm}>
        <HuGoThemeProvider>{groupMembersReportDrawer}</HuGoThemeProvider>
      </FormProvider>
      <Stack sx={{ justifyContent: 'space-between', flexDirection: 'row' }}>
        <Title
          title={t('group:members')}
          description={t('group:members_description')}
          variant="L"
        />
        {isDownloadGroupMembersReportEnabled && (
          <Button
            variant="outlined"
            onClick={() => showGroupMembersReportDrawer()}
            startIcon={<IconDownload />}
          >
            {t('group:report_download')}
          </Button>
        )}
      </Stack>

      <HuAlert
        title={t('group:manage_members_alert_title')}
        description={t('group:manage_members_alert_info')}
        severity="info"
        hasClose
      />
      <Stack
        sx={theme => ({
          p: 2,
          backgroundColor: theme.palette.new.background.layout.tertiary,
          borderRadius: theme.shape.borderRadiusL,
        })}
      >
        <Stack
          sx={theme => ({
            p: 2,
            backgroundColor: theme.palette.new.background.layout.default,
            borderRadius: theme.shape.borderRadiusL,
            mb: 3,
          })}
        >
          <Search
            value={query}
            onChange={setQuery}
            placeholder={t('general:search')}
          />
        </Stack>
        <InfiniteList
          isSuccess={isSuccess}
          hasNextPage={hasNextPage}
          isFetchingNextPage={isFetchingNextPage}
          fetchNextPage={fetchNextPage}
          isEmpty={isEmpty}
          isLoading={isLoading}
          noResultsLabel={<NoResultsLabel />}
        >
          <TableContainer>
            <Table>
              <TableHead>
                <TableRow headerRow>
                  <TableCell
                    headerCell
                    id="FULL_NAME"
                  >
                    {t('group:member_name')}
                  </TableCell>
                  {groupDetails?.isMultiCompany && (
                    <TableCell
                      headerCell
                      id="COMMUNITY"
                    >
                      {t('group:member_community')}
                    </TableCell>
                  )}
                  <TableCell
                    headerCell
                    id="ROLE"
                  >
                    {t('group:member_role')}
                  </TableCell>
                  <TableCell
                    headerCell
                    id="MAIL"
                  >
                    {t('group:member_mail')}
                  </TableCell>
                  <TableCell
                    headerCell
                    id="CREATED_AT"
                  >
                    {t('group:member_joined_date')}
                  </TableCell>
                  <TableCell headerCell />
                </TableRow>
              </TableHead>

              <TableBody>
                {members.map(member => (
                  <TableRow key={member.userId}>
                    <TableCell
                      component="th"
                      scope="row"
                      sx={{
                        gap: 1,
                        display: 'flex',
                        alignItems: 'center',
                        borderBottom: 'none',
                      }}
                    >
                      {member.user && (
                        <UserNameLink
                          user={{
                            ...member.user,
                            isExternal: member.isExternal,
                          }}
                          showProfilePicture
                          sx={{ fontWeight: 400 }}
                        />
                      )}
                    </TableCell>
                    {groupDetails?.isMultiCompany && (
                      <TableCell align="left">
                        <EllipsisTooltip title={member.instanceName ?? ''}>
                          <Typography
                            noWrap
                            sx={{
                              maxWidth: 150,
                            }}
                          >
                            {member.instanceName}
                          </Typography>
                        </EllipsisTooltip>
                      </TableCell>
                    )}
                    <TableCell align="left">
                      {t(`group:${member.role.toLowerCase()}`)}
                    </TableCell>
                    <TableCell align="left">
                      <EllipsisTooltip title={member.user?.email ?? ''}>
                        <Typography
                          noWrap
                          sx={{
                            maxWidth: 100,
                          }}
                        >
                          {member.user?.email}
                        </Typography>
                      </EllipsisTooltip>
                    </TableCell>
                    <TableCell
                      component="th"
                      scope="row"
                    >
                      {formatUTCDate(member.createdAt)}
                    </TableCell>
                    <TableCell align="left">
                      {user && member.userId !== user.id && (
                        <MenuList
                          options={[
                            {
                              onClick: () =>
                                handleUpdateMemberRole(
                                  member.userId,
                                  member.role,
                                ),
                              Icon: isAdmin(member.role)
                                ? IconShieldMinus
                                : IconShieldPlus,
                              title: t('group:update_role', {
                                context: member.role.toLowerCase(),
                              }),
                              disabled: !isSameInstance(
                                member.instanceId,
                                instance?.id,
                              ),
                            },
                            {
                              onClick: () =>
                                showDeleteMemberModal({
                                  userId: member.userId,
                                }),
                              Icon: IconTrash,
                              title: t('group:remove_member'),
                              disabled: isSourceSegmentation(member.source),
                            },
                          ]}
                        />
                      )}
                    </TableCell>
                  </TableRow>
                ))}
              </TableBody>
            </Table>
          </TableContainer>
        </InfiniteList>
        {showNoMoreResultsFooter && (
          <Stack sx={{ mt: 1 }}>
            <NoMoreResultsFooter
              scrollableElementId={GROUP_MANAGEMENT_LAYOUT_CONTENT_ID}
            />
          </Stack>
        )}
      </Stack>
    </Stack>
  );
};

export default ManageMembers;
