import { useMemo, useState } from 'react';
import { useFormContext } from 'react-hook-form';
import { useInfiniteQuery } from 'react-query';

import { useDrawerV2 } from '@material-hu/hooks/useDrawerV2';
import Stack from '@material-hu/mui/Stack';
import { appearFromBottom } from '@material-hu/utils/animations';

import UserAvatar from '@material-hu/components/composed-components/UserAvatar';
import Checkbox from '@material-hu/components/design-system/Checkbox/Checkbox';
import Search from '@material-hu/components/design-system/Inputs/Search';
import StateCard from '@material-hu/components/design-system/StateCard';

import { type User } from 'src/types/user';
import { useLokaliseTranslation } from 'src/utils/i18n';
import { sToMs } from 'src/utils/timeUtils';

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

import { type ApprovalStepsUsersService } from './types';

const COLLABORATORS_PAGE_LIMIT = 30;

type Props = {
  name: string;
  usersService: ApprovalStepsUsersService;
};

type ContentProps = {
  isDrawerOpen: boolean;
  search: string;
  setSearch: (value: string) => void;
  selectedUsers: User[];
  onSelectUser: (user: User) => void;
  usersService: ApprovalStepsUsersService;
};

const CollaboratorsSelectionDrawerContent = ({
  isDrawerOpen,
  search,
  setSearch,
  selectedUsers,
  onSelectUser,
  usersService,
}: ContentProps) => {
  const { t } = useLokaliseTranslation('general');
  const {
    data: users,
    isLoading,
    fetchNextPage,
    hasNextPage,
    isFetchingNextPage,
  } = useInfiniteQuery(
    usersService.queryKey({ search, limit: COLLABORATORS_PAGE_LIMIT }),
    ({ pageParam = 0 }) =>
      usersService.getUsers({
        search,
        limit: COLLABORATORS_PAGE_LIMIT,
        page: pageParam,
      }),
    {
      enabled: isDrawerOpen,
      staleTime: sToMs(60),
      getNextPageParam: usersService.getNextPageParam,
    },
  );

  const usersList = useMemo(
    () => users?.pages.flatMap(page => page.data.items) || [],
    [users],
  );

  return (
    <Stack sx={{ gap: 2 }}>
      <Search
        value={search}
        onChange={setSearch}
      />
      {!usersList?.length && !isLoading && (
        <StateCard
          title={t('no_results_for_search')}
          description={t('try_again_with_other_words')}
          slotProps={{
            card: {
              sx: {
                animation: `${appearFromBottom} 125ms ease-in-out backwards`,
              },
            },
          }}
        />
      )}
      {(!!usersList?.length || isLoading) && (
        <InfiniteList
          isSuccess={!!users}
          isLoading={isLoading}
          isEmpty={!!users && !users?.pages?.length}
          fetchNextPage={fetchNextPage}
          hasNextPage={!!hasNextPage}
          isFetchingNextPage={isFetchingNextPage}
          sx={{ p: 0 }}
        >
          <Stack>
            {usersList.map(user => (
              <Stack
                key={`${user.id}-${user.employeeInternalId}`}
                sx={{ flexDirection: 'row', alignItems: 'center', gap: 1 }}
              >
                <Checkbox
                  checked={selectedUsers.some(u => u.id === user.id)}
                  onChange={() => onSelectUser(user)}
                />
                <UserAvatar
                  user={user}
                  profileProps={{ showEmployeeInternalId: true }}
                  sx={{ maxWidth: 500 }}
                />
              </Stack>
            ))}
          </Stack>
        </InfiniteList>
      )}
    </Stack>
  );
};

export const useCollabSelectionDrawer = ({ name, usersService }: Props) => {
  const { t } = useLokaliseTranslation('approval_requests');
  const form = useFormContext();
  const [search, setSearch] = useState('');
  const [pendingUsers, setPendingUsers] = useState<User[]>([]);

  const handleSelectUser = (user: User) => {
    setPendingUsers(prev =>
      prev.some(u => u.id === user.id)
        ? prev.filter(u => u.id !== user.id)
        : [...prev, user],
    );
  };

  const handleDrawerClose = () => {
    setSearch('');
    closeDrawer();
  };

  const { drawer, showDrawer, closeDrawer } = useDrawerV2(({ open }) => ({
    title: t('general:select_people'),
    children: (
      <CollaboratorsSelectionDrawerContent
        isDrawerOpen={open}
        search={search}
        setSearch={setSearch}
        selectedUsers={pendingUsers}
        usersService={usersService}
        onSelectUser={handleSelectUser}
      />
    ),
    primaryButtonProps: {
      children: t('general:apply'),
      onClick: () => {
        form.setValue(name, pendingUsers);
        handleDrawerClose();
      },
    },
    secondaryButtonProps: {
      children: t('general:cancel'),
      onClick: handleDrawerClose,
    },
    onClose: handleDrawerClose,
  }));

  const showCollaboratorsSelectionDrawer = () => {
    setPendingUsers(form.getValues(name) ?? []);
    showDrawer({});
  };

  return {
    collaboratorsSelectionDrawer: drawer,
    showCollaboratorsSelectionDrawer,
  };
};
