import { FC, useEffect, useMemo } from 'react';
import { FormProvider, useFormContext } from 'react-hook-form';

import { useServerPagination } from '@material-hu/hooks/useServerPagination';
import {
  IconExclamationCircle,
  IconInfoSquareRounded,
} from '@material-hu/icons/tabler';
import Divider from '@material-hu/mui/Divider';
import Radio from '@material-hu/mui/Radio';
import Stack from '@material-hu/mui/Stack';
import Typography from '@material-hu/mui/Typography';
import { colorPalette } from '@material-hu/theme/hugo/colors';

import HuAvatar from '@material-hu/components/design-system/Avatar';
import HuRadioButton from '@material-hu/components/design-system/RadioButton/RadioButton';
import HuSkeleton from '@material-hu/components/design-system/Skeleton';
import HuTitle from '@material-hu/components/design-system/Title';

import useHuGoTheme from 'src/hooks/useHuGoTheme';
import { useInfiniteUsersPublicSearch } from 'src/services/usersQueries';
import { FlowNode, NodeType } from 'src/types/workflows';

import { useLokaliseTranslation } from 'src/utils/i18n';

import { getFullname } from 'src/utils/userUtils';

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

import { InvalidNodeInfo, useHydratedUsers } from '../../utils';

const usersSkeleton = (isFetching: boolean = false) => (
  <Stack>
    {Array.from({ length: 3 }, (_, index) => (
      <Stack
        key={index}
        sx={{ gap: 2, py: 1 }}
      >
        {(index > 0 || !isFetching) && <Divider />}
        <Stack
          sx={{
            flexDirection: 'row',
            alignItems: 'center',
            gap: 1,
          }}
        >
          <Radio sx={{ p: 0, pr: 1 }} />
          <HuSkeleton
            width={38}
            height={30}
            variant="circular"
            isLoading
          />
          <HuSkeleton
            height={35}
            width="100%"
            isLoading
          />
        </Stack>
      </Stack>
    ))}
  </Stack>
);

type ChangeFieldAssigneeProps = {
  node?: FlowNode;
  invalidNodes?: InvalidNodeInfo[];
};

const ChangeFieldAssignee: FC<ChangeFieldAssigneeProps> = ({
  node,
  invalidNodes,
}) => {
  const HuGoThemeProvider = useHuGoTheme();
  const { t } = useLokaliseTranslation(['workflows', 'general']);
  const form = useFormContext();
  const isEditing = !!node;

  useEffect(() => {
    if (isEditing) form.setValue('node', node);
    const isNewNode = form.getValues('node').type === NodeType.NEW;

    form.setValue('node.type', NodeType.CHANGE_ASSIGNEE);
    form.setValue('node.newStateId', undefined);

    if (isNewNode) {
      form.setValue('node.name', t('update_assignee'));
    }
  }, []);

  const nodeIsInvalid = invalidNodes?.some(
    n => n.id === form.getValues('node').id,
  );
  const showError = nodeIsInvalid && !form.watch('node.newAssigneeId');

  const { query, Searchbar } = useServerPagination();
  const newAssigneeId = form.watch('node.newAssigneeId');
  const { hydratedUsers, isFetching: isFetchingHydrated } = useHydratedUsers(
    newAssigneeId ? [newAssigneeId] : [],
    !!newAssigneeId,
  );

  const {
    data,
    isLoading: loading,
    isFetching,
    fetchNextPage,
    hasNextPage,
    isFetchingNextPage,
  } = useInfiniteUsersPublicSearch({
    search: query || '',
    limit: 10,
    isAgent: true,
  });

  const isLoading =
    loading || (isFetching && !isFetchingNextPage) || isFetchingHydrated;
  const paginatedUsers = data?.pages.flatMap(page => page.data.items) || [];
  const totalCount = data?.pages[0]?.data?.count;

  // Combine first page with already selected
  const users = useMemo(() => {
    const selectedUser = hydratedUsers?.[0];
    if (!hydratedUsers?.[0] || query) return paginatedUsers;

    const filteredPaginatedUsers = paginatedUsers.filter(
      user => user.id !== selectedUser.id,
    );

    return [selectedUser, ...filteredPaginatedUsers];
  }, [hydratedUsers, paginatedUsers, query]);

  return (
    <HuGoThemeProvider>
      <FormProvider {...form}>
        <Stack sx={{ height: '100%', gap: 2 }}>
          <Typography variant="globalS">
            {t('change_assignee_description')}
          </Typography>
          <Searchbar placeholder={t('general:search')} />
          <Stack
            sx={{
              flex: 1,
              overflow: 'auto',
              pr: 1,
            }}
          >
            {showError && (
              <Stack
                sx={{
                  flexDirection: 'row',
                  alignItems: 'center',
                  gap: 0.5,
                  mt: 1,
                }}
              >
                <IconExclamationCircle
                  size={16}
                  color={colorPalette.textColors?.errorText}
                />
                <Typography
                  variant="globalS"
                  color={colorPalette.textColors?.errorText}
                >
                  {t('error_assignee_required')}
                </Typography>
              </Stack>
            )}
            <Stack
              sx={{
                backgroundColor: theme =>
                  theme.palette.hugoBackground?.neutralBg,
                borderRadius: 2,
                gap: 2,
                p: 2,
                mt: 2,
              }}
            >
              {!isLoading && !!users.length && (
                <InfiniteList
                  isSuccess={!!data}
                  isLoading={isLoading}
                  isEmpty={data?.pages && !totalCount}
                  fetchNextPage={fetchNextPage}
                  hasNextPage={!!hasNextPage}
                  isFetchingNextPage={isFetchingNextPage}
                  renderSkeleton={usersSkeleton()}
                >
                  {users.map((user, index) => (
                    <Stack key={user.id}>
                      <Stack
                        sx={{
                          flexDirection: 'row',
                          alignItems: 'center',
                          gap: 1,
                        }}
                        onClick={() =>
                          form.setValue('node.newAssigneeId', user.id)
                        }
                      >
                        <HuRadioButton
                          label={getFullname(user)}
                          isActive={newAssigneeId === user.id}
                          avatarProps={{
                            src: user.profilePicture || '',
                            size: 'small',
                          }}
                          labelProps={{
                            variant: 'globalS',
                            fontWeight: 'semiBold',
                          }}
                        />
                      </Stack>
                      {index < users.length - 1 && <Divider sx={{ my: 2 }} />}
                    </Stack>
                  ))}
                </InfiniteList>
              )}
              {!isLoading && !users.length && !query && (
                <HuTitle
                  variant="M"
                  title={t('no_agents')}
                  description={t('no_agents_sub')}
                />
              )}
              {!isLoading && !users.length && query && (
                <Stack sx={{ alignItems: 'center', gap: 2 }}>
                  <HuAvatar
                    size="large"
                    Icon={IconInfoSquareRounded}
                    color="primary"
                  />
                  <HuTitle
                    variant="M"
                    centered
                    title={t('empty_agents')}
                    description={t('empty_agents_sub')}
                  />
                </Stack>
              )}
              {isLoading && usersSkeleton(true)}
            </Stack>
          </Stack>
        </Stack>
      </FormProvider>
    </HuGoThemeProvider>
  );
};

export default ChangeFieldAssignee;
